* Fix undefined method error in sidekiq Body can be not nil but still be empty, which causes a `NoMethodError: undefined method `[]' for nil:NilClass` further in the code. This checks for an empty body to avoid the issue. * Fix codeclimate issue
		
			
				
	
	
		
			71 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			71 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| class FetchOEmbedService
 | |
|   attr_reader :url, :options, :format, :endpoint_url
 | |
| 
 | |
|   def call(url, options = {})
 | |
|     @url     = url
 | |
|     @options = options
 | |
| 
 | |
|     discover_endpoint!
 | |
|     fetch!
 | |
|   end
 | |
| 
 | |
|   private
 | |
| 
 | |
|   def discover_endpoint!
 | |
|     return if html.nil?
 | |
| 
 | |
|     @format = @options[:format]
 | |
|     page    = Nokogiri::HTML(html)
 | |
| 
 | |
|     if @format.nil? || @format == :json
 | |
|       @endpoint_url ||= page.at_xpath('//link[@type="application/json+oembed"]')&.attribute('href')&.value
 | |
|       @format       ||= :json if @endpoint_url
 | |
|     end
 | |
| 
 | |
|     if @format.nil? || @format == :xml
 | |
|       @endpoint_url ||= page.at_xpath('//link[@type="text/xml+oembed"]')&.attribute('href')&.value
 | |
|       @format       ||= :xml if @endpoint_url
 | |
|     end
 | |
| 
 | |
|     return if @endpoint_url.blank?
 | |
| 
 | |
|     @endpoint_url = (Addressable::URI.parse(@url) + @endpoint_url).to_s
 | |
|   rescue Addressable::URI::InvalidURIError
 | |
|     @endpoint_url = nil
 | |
|   end
 | |
| 
 | |
|   def fetch!
 | |
|     return if @endpoint_url.blank?
 | |
| 
 | |
|     body = Request.new(:get, @endpoint_url).perform do |res|
 | |
|       res.code != 200 ? nil : res.body_with_limit
 | |
|     end
 | |
| 
 | |
|     validate(parse_for_format(body)) if body.present?
 | |
|   rescue Oj::ParseError, Ox::ParseError
 | |
|     nil
 | |
|   end
 | |
| 
 | |
|   def parse_for_format(body)
 | |
|     case @format
 | |
|     when :json
 | |
|       Oj.load(body, mode: :strict)&.with_indifferent_access
 | |
|     when :xml
 | |
|       Ox.load(body, mode: :hash_no_attrs)&.with_indifferent_access&.dig(:oembed)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def validate(oembed)
 | |
|     oembed if oembed[:version] == '1.0' && oembed[:type].present?
 | |
|   end
 | |
| 
 | |
|   def html
 | |
|     return @html if defined?(@html)
 | |
| 
 | |
|     @html = @options[:html] || Request.new(:get, @url).perform do |res|
 | |
|       res.code != 200 || res.mime_type != 'text/html' ? nil : res.body_with_limit
 | |
|     end
 | |
|   end
 | |
| end
 |