Add basic support for remote attachments with multiple media types (#34996)

This commit is contained in:
Claire 2025-06-10 15:26:29 +02:00 committed by GitHub
parent c727701839
commit 7a7e0ba4cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 2 deletions

View file

@ -26,6 +26,8 @@ module JsonLdHelper
# The url attribute can be a string, an array of strings, or an array of objects. # The url attribute can be a string, an array of strings, or an array of objects.
# The objects could include a mimeType. Not-included mimeType means it's text/html. # The objects could include a mimeType. Not-included mimeType means it's text/html.
def url_to_href(value, preferred_type = nil) def url_to_href(value, preferred_type = nil)
value = [value] if value.is_a?(Hash)
single_value = if value.is_a?(Array) && !value.first.is_a?(String) single_value = if value.is_a?(Array) && !value.first.is_a?(String)
value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) } value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
elsif value.is_a?(Array) elsif value.is_a?(Array)
@ -41,6 +43,15 @@ module JsonLdHelper
end end
end end
def url_to_media_type(value, preferred_type = nil)
value = [value] if value.is_a?(Hash)
return unless value.is_a?(Array) && !value.first.is_a?(String)
single_value = value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
single_value['mediaType'] unless single_value.nil?
end
def as_array(value) def as_array(value)
if value.nil? if value.nil?
[] []

View file

@ -15,7 +15,7 @@ class ActivityPub::Parser::MediaAttachmentParser
end end
def remote_url def remote_url
url = Addressable::URI.parse(@json['url'])&.normalize&.to_s url = Addressable::URI.parse(url_to_href(@json['url']))&.normalize&.to_s
url unless unsupported_uri_scheme?(url) url unless unsupported_uri_scheme?(url)
rescue Addressable::URI::InvalidURIError rescue Addressable::URI::InvalidURIError
nil nil
@ -43,7 +43,7 @@ class ActivityPub::Parser::MediaAttachmentParser
end end
def file_content_type def file_content_type
@json['mediaType'] @json['mediaType'] || url_to_media_type(@json['url'])
end end
private private

View file

@ -0,0 +1,51 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ActivityPub::Parser::MediaAttachmentParser do
subject { described_class.new(json) }
let(:json) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
type: 'Document',
mediaType: 'image/png',
url: 'http://example.com/attachment.png',
}.deep_stringify_keys
end
it 'correctly parses media attachment' do
expect(subject).to have_attributes(
remote_url: 'http://example.com/attachment.png',
file_content_type: 'image/png'
)
end
context 'when the URL is a link with multiple options' do
let(:json) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
type: 'Document',
url: [
{
type: 'Link',
mediaType: 'image/png',
href: 'http://example.com/attachment.png',
},
{
type: 'Link',
mediaType: 'image/avif',
href: 'http://example.com/attachment.avif',
},
],
}.deep_stringify_keys
end
it 'returns the first option' do
expect(subject).to have_attributes(
remote_url: 'http://example.com/attachment.png',
file_content_type: 'image/png'
)
end
end
end