Class: Html2rss::RequestService::Response

Inherits:
Object
  • Object
show all
Defined in:
lib/html2rss/request_service/response.rb

Overview

To be used by strategies to provide their response.

Constant Summary collapse

EMPTY_TRANSPORT_META =

Default when a strategy does not attach transport telemetry.

{}.freeze
EMPTY_CAPTURED_RESPONSES =

Default when a strategy does not capture sub-resource responses.

[].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(body:, url:, headers: {}, status: nil, transport_meta: EMPTY_TRANSPORT_META, captured_responses: EMPTY_CAPTURED_RESPONSES) ⇒ Response

rubocop:disable Metrics/MethodLength, Metrics/ParameterLists -- transport + capture fields stay co-located

Parameters:

  • body (String)

    the body of the response

  • url (Html2rss::Url)

    the final request URL

  • headers (Hash) (defaults to: {})

    the headers of the response

  • status (Integer, nil) (defaults to: nil)

    the HTTP status code when available

  • transport_meta (Hash) (defaults to: EMPTY_TRANSPORT_META)

    allowlisted upstream telemetry (frozen when present)

  • captured_responses (Array<Hash>) (defaults to: EMPTY_CAPTURED_RESPONSES)

    JSON XHR/fetch bodies captured during browser scrapes



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/html2rss/request_service/response.rb', line 23

def initialize(body:, url:, headers: {}, status: nil, transport_meta: EMPTY_TRANSPORT_META,
               captured_responses: EMPTY_CAPTURED_RESPONSES)
  @body = body

  headers = headers.dup
  headers.transform_keys!(&:to_s)
  HashUtil.assert_string_keys!(headers, context: 'response headers', deep: false)

  @headers = headers
  @status = status
  @url = url
  @transport_meta = transport_meta.nil? || transport_meta.empty? ? EMPTY_TRANSPORT_META : transport_meta.freeze
  @captured_responses = if captured_responses.nil? || captured_responses.empty?
                          EMPTY_CAPTURED_RESPONSES
                        else
                          captured_responses.freeze
                        end
end

Instance Attribute Details

#bodyString (readonly)

Returns the raw body of the response.

Returns:

  • (String)

    the raw body of the response



44
45
46
# File 'lib/html2rss/request_service/response.rb', line 44

def body
  @body
end

#captured_responsesArray<Hash> (readonly)

Returns captured JSON XHR/fetch responses (empty when unsupported).

Returns:

  • (Array<Hash>)

    captured JSON XHR/fetch responses (empty when unsupported)



59
60
61
# File 'lib/html2rss/request_service/response.rb', line 59

def captured_responses
  @captured_responses
end

#headersHash{String => Object} (readonly)

Returns the headers of the response.

Returns:

  • (Hash{String => Object})

    the headers of the response



47
48
49
# File 'lib/html2rss/request_service/response.rb', line 47

def headers
  @headers
end

#statusInteger? (readonly)

Returns the HTTP status code when known.

Returns:

  • (Integer, nil)

    the HTTP status code when known



50
51
52
# File 'lib/html2rss/request_service/response.rb', line 50

def status
  @status
end

#transport_metaHash (readonly)

Returns allowlisted upstream transport telemetry.

Returns:

  • (Hash)

    allowlisted upstream transport telemetry



56
57
58
# File 'lib/html2rss/request_service/response.rb', line 56

def transport_meta
  @transport_meta
end

#urlHtml2rss::Url (readonly)

Returns the URL of the response.

Returns:



53
54
55
# File 'lib/html2rss/request_service/response.rb', line 53

def url
  @url
end

Instance Method Details

#content_typeString

Returns normalized content type header value.

Returns:

  • (String)

    normalized content type header value



62
# File 'lib/html2rss/request_service/response.rb', line 62

def content_type = header('content-type').to_s

#html_response?Boolean

Returns whether response content is HTML.

Returns:

  • (Boolean)

    whether response content is HTML



68
# File 'lib/html2rss/request_service/response.rb', line 68

def html_response? = content_type.include?('text/html')

#json_response?Boolean

Returns whether response content is JSON.

Returns:

  • (Boolean)

    whether response content is JSON



65
# File 'lib/html2rss/request_service/response.rb', line 65

def json_response? = content_type.include?('application/json')

#parsed_bodyNokogiri::HTML::Document, Hash

Returns the parsed body of the response, frozen object.

Returns:

  • (Nokogiri::HTML::Document, Hash)

    the parsed body of the response, frozen object

Raises:



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/html2rss/request_service/response.rb', line 73

def parsed_body
  @parsed_body ||= if html_response?
                     Nokogiri::HTML(body).tap do |doc|
                       # Remove comments from the document to avoid processing irrelevant content
                       doc.xpath('//comment()').each(&:remove)
                     end.freeze
                   elsif json_response?
                     JSON.parse(body, symbolize_names: true).freeze
                   else
                     raise UnsupportedResponseContentType, "Unsupported content type: #{content_type}"
                   end
end