You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.3 KiB

  1. # frozen_string_literal: true
  2. class FetchAtomService < BaseService
  3. def call(url)
  4. return if url.blank?
  5. @url = url
  6. perform_request
  7. process_response
  8. rescue OpenSSL::SSL::SSLError => e
  9. Rails.logger.debug "SSL error: #{e}"
  10. nil
  11. rescue HTTP::ConnectionError => e
  12. Rails.logger.debug "HTTP ConnectionError: #{e}"
  13. nil
  14. end
  15. private
  16. def perform_request
  17. @response = Request.new(:get, @url)
  18. .add_headers('Accept' => 'application/activity+json, application/ld+json, application/atom+xml, text/html')
  19. .perform
  20. end
  21. def process_response(terminal = false)
  22. return nil if @response.code != 200
  23. if @response.mime_type == 'application/atom+xml'
  24. [@url, @response.to_s, :ostatus]
  25. elsif ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(@response.mime_type)
  26. [@url, @response.to_s, :activitypub]
  27. elsif @response['Link'] && !terminal
  28. process_headers
  29. elsif @response.mime_type == 'text/html' && !terminal
  30. process_html
  31. end
  32. end
  33. def process_html
  34. page = Nokogiri::HTML(@response.to_s)
  35. json_link = page.xpath('//link[@rel="alternate"]').find { |link| ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(link['type']) }
  36. atom_link = page.xpath('//link[@rel="alternate"]').find { |link| link['type'] == 'application/atom+xml' }
  37. if !json_link.nil?
  38. @url = json_link['href']
  39. perform_request
  40. process_response(true)
  41. elsif !atom_link.nil?
  42. @url = atom_link['href']
  43. perform_request
  44. process_response(true)
  45. end
  46. end
  47. def process_headers
  48. link_header = LinkHeader.parse(@response['Link'].is_a?(Array) ? @response['Link'].first : @response['Link'])
  49. json_link = link_header.find_link(%w(rel alternate), %w(type application/activity+json)) || link_header.find_link(%w(rel alternate), ['type', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'])
  50. atom_link = link_header.find_link(%w(rel alternate), %w(type application/atom+xml))
  51. if !json_link.nil?
  52. @url = json_link.href
  53. perform_request
  54. process_response(true)
  55. elsif !atom_link.nil?
  56. @url = atom_link.href
  57. perform_request
  58. process_response(true)
  59. end
  60. end
  61. end