Fix redundant HTTP request in FetchLinkCardService (#6002)
This commit is contained in:
		
							parent
							
								
									20a6584d2d
								
							
						
					
					
						commit
						a8deb6648b
					
				|  | @ -2,13 +2,26 @@ | ||||||
| 
 | 
 | ||||||
| class ProviderDiscovery < OEmbed::ProviderDiscovery | class ProviderDiscovery < OEmbed::ProviderDiscovery | ||||||
|   class << self |   class << self | ||||||
|  |     def get(url, **options) | ||||||
|  |       provider = discover_provider(url, options) | ||||||
|  | 
 | ||||||
|  |       options.delete(:html) | ||||||
|  | 
 | ||||||
|  |       provider.get(url, options) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     def discover_provider(url, **options) |     def discover_provider(url, **options) | ||||||
|       res    = Request.new(:get, url).perform |  | ||||||
|       format = options[:format] |       format = options[:format] | ||||||
| 
 | 
 | ||||||
|       raise OEmbed::NotFound, url if res.code != 200 || res.mime_type != 'text/html' |       if options[:html] | ||||||
|  |         html = Nokogiri::HTML(options[:html]) | ||||||
|  |       else | ||||||
|  |         res = Request.new(:get, url).perform | ||||||
| 
 | 
 | ||||||
|       html = Nokogiri::HTML(res.to_s) |         raise OEmbed::NotFound, url if res.code != 200 || res.mime_type != 'text/html' | ||||||
|  | 
 | ||||||
|  |         html = Nokogiri::HTML(res.to_s) | ||||||
|  |       end | ||||||
| 
 | 
 | ||||||
|       if format.nil? || format == :json |       if format.nil? || format == :json | ||||||
|         provider_endpoint ||= html.at_xpath('//link[@type="application/json+oembed"]')&.attribute('href')&.value |         provider_endpoint ||= html.at_xpath('//link[@type="application/json+oembed"]')&.attribute('href')&.value | ||||||
|  |  | ||||||
|  | @ -40,6 +40,12 @@ class FetchLinkCardService < BaseService | ||||||
| 
 | 
 | ||||||
|     return if res.code != 405 && (res.code != 200 || res.mime_type != 'text/html') |     return if res.code != 405 && (res.code != 200 || res.mime_type != 'text/html') | ||||||
| 
 | 
 | ||||||
|  |     @response = Request.new(:get, @url).perform | ||||||
|  | 
 | ||||||
|  |     return if @response.code != 200 || @response.mime_type != 'text/html' | ||||||
|  | 
 | ||||||
|  |     @html = @response.to_s | ||||||
|  | 
 | ||||||
|     attempt_oembed || attempt_opengraph |     attempt_oembed || attempt_opengraph | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  | @ -70,32 +76,32 @@ class FetchLinkCardService < BaseService | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def attempt_oembed |   def attempt_oembed | ||||||
|     response = OEmbed::Providers.get(@url) |     embed = OEmbed::Providers.get(@url, html: @html) | ||||||
| 
 | 
 | ||||||
|     return false unless response.respond_to?(:type) |     return false unless embed.respond_to?(:type) | ||||||
| 
 | 
 | ||||||
|     @card.type          = response.type |     @card.type          = embed.type | ||||||
|     @card.title         = response.respond_to?(:title)         ? response.title         : '' |     @card.title         = embed.respond_to?(:title)         ? embed.title         : '' | ||||||
|     @card.author_name   = response.respond_to?(:author_name)   ? response.author_name   : '' |     @card.author_name   = embed.respond_to?(:author_name)   ? embed.author_name   : '' | ||||||
|     @card.author_url    = response.respond_to?(:author_url)    ? response.author_url    : '' |     @card.author_url    = embed.respond_to?(:author_url)    ? embed.author_url    : '' | ||||||
|     @card.provider_name = response.respond_to?(:provider_name) ? response.provider_name : '' |     @card.provider_name = embed.respond_to?(:provider_name) ? embed.provider_name : '' | ||||||
|     @card.provider_url  = response.respond_to?(:provider_url)  ? response.provider_url  : '' |     @card.provider_url  = embed.respond_to?(:provider_url)  ? embed.provider_url  : '' | ||||||
|     @card.width         = 0 |     @card.width         = 0 | ||||||
|     @card.height        = 0 |     @card.height        = 0 | ||||||
| 
 | 
 | ||||||
|     case @card.type |     case @card.type | ||||||
|     when 'link' |     when 'link' | ||||||
|       @card.image = URI.parse(response.thumbnail_url) if response.respond_to?(:thumbnail_url) |       @card.image = URI.parse(embed.thumbnail_url) if embed.respond_to?(:thumbnail_url) | ||||||
|     when 'photo' |     when 'photo' | ||||||
|       return false unless response.respond_to?(:url) |       return false unless embed.respond_to?(:url) | ||||||
|       @card.embed_url = response.url |       @card.embed_url = embed.url | ||||||
|       @card.image     = URI.parse(response.url) |       @card.image     = URI.parse(embed.url) | ||||||
|       @card.width     = response.width.presence  || 0 |       @card.width     = embed.width.presence  || 0 | ||||||
|       @card.height    = response.height.presence || 0 |       @card.height    = embed.height.presence || 0 | ||||||
|     when 'video' |     when 'video' | ||||||
|       @card.width  = response.width.presence  || 0 |       @card.width  = embed.width.presence  || 0 | ||||||
|       @card.height = response.height.presence || 0 |       @card.height = embed.height.presence || 0 | ||||||
|       @card.html   = Formatter.instance.sanitize(response.html, Sanitize::Config::MASTODON_OEMBED) |       @card.html   = Formatter.instance.sanitize(embed.html, Sanitize::Config::MASTODON_OEMBED) | ||||||
|     when 'rich' |     when 'rich' | ||||||
|       # Most providers rely on <script> tags, which is a no-no |       # Most providers rely on <script> tags, which is a no-no | ||||||
|       return false |       return false | ||||||
|  | @ -107,17 +113,11 @@ class FetchLinkCardService < BaseService | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def attempt_opengraph |   def attempt_opengraph | ||||||
|     response = Request.new(:get, @url).perform |  | ||||||
| 
 |  | ||||||
|     return if response.code != 200 || response.mime_type != 'text/html' |  | ||||||
| 
 |  | ||||||
|     html = response.to_s |  | ||||||
| 
 |  | ||||||
|     detector = CharlockHolmes::EncodingDetector.new |     detector = CharlockHolmes::EncodingDetector.new | ||||||
|     detector.strip_tags = true |     detector.strip_tags = true | ||||||
| 
 | 
 | ||||||
|     guess = detector.detect(html, response.charset) |     guess = detector.detect(@html, @response.charset) | ||||||
|     page  = Nokogiri::HTML(html, nil, guess&.fetch(:encoding, nil)) |     page  = Nokogiri::HTML(@html, nil, guess&.fetch(:encoding, nil)) | ||||||
| 
 | 
 | ||||||
|     if meta_property(page, 'twitter:player') |     if meta_property(page, 'twitter:player') | ||||||
|       @card.type   = :video |       @card.type   = :video | ||||||
|  | @ -134,16 +134,16 @@ class FetchLinkCardService < BaseService | ||||||
|       @card.image_remote_url = meta_property(page, 'og:image') if meta_property(page, 'og:image') |       @card.image_remote_url = meta_property(page, 'og:image') if meta_property(page, 'og:image') | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     @card.title            = meta_property(page, 'og:title').presence || page.at_xpath('//title')&.content || '' |     @card.title       = meta_property(page, 'og:title').presence || page.at_xpath('//title')&.content || '' | ||||||
|     @card.description      = meta_property(page, 'og:description').presence || meta_property(page, 'description') || '' |     @card.description = meta_property(page, 'og:description').presence || meta_property(page, 'description') || '' | ||||||
| 
 | 
 | ||||||
|     return if @card.title.blank? && @card.html.blank? |     return if @card.title.blank? && @card.html.blank? | ||||||
| 
 | 
 | ||||||
|     @card.save_with_optional_image! |     @card.save_with_optional_image! | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def meta_property(html, property) |   def meta_property(page, property) | ||||||
|     html.at_xpath("//meta[@property=\"#{property}\"]")&.attribute('content')&.value || html.at_xpath("//meta[@name=\"#{property}\"]")&.attribute('content')&.value |     page.at_xpath("//meta[@property=\"#{property}\"]")&.attribute('content')&.value || page.at_xpath("//meta[@name=\"#{property}\"]")&.attribute('content')&.value | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def lock_options |   def lock_options | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue