Class: X::Response
- Inherits:
-
Object
- Object
- X::Response
- Includes:
- ResponseHeaders
- Defined in:
- x-core/lib/x/core/response.rb
Overview
A summary of one API response, or one object of a stream, which a client passes to its on_response hook
Instance Attribute Summary collapse
-
#http_method ⇒ Symbol
readonly
The HTTP method of the request.
-
#http_response ⇒ Net::HTTPResponse
readonly
The response itself, as the client received it.
-
#uri ⇒ URI::Generic
readonly
The URI of the request.
Instance Method Summary collapse
-
#body ⇒ String?
The body summarized: one streamed object, or else the whole body.
-
#headers ⇒ Hash{String => String}
The headers of the response.
-
#initialize(http_method:, uri:, http_response: nil, status: nil, headers: nil, body: nil) ⇒ Response
constructor
Summarize a response.
-
#rate_limit ⇒ RateLimit?
The 15-minute rate limit of the endpoint, which nearly every response reports.
-
#rate_limits ⇒ Array<RateLimit>
The rate limits the response reports in its headers.
-
#resource_count ⇒ Integer
The number of resources the body holds, in data and includes together.
-
#resource_counts ⇒ Hash{String => Integer}
The number of resources the body holds, as data and as each kind of include.
-
#status ⇒ Integer
The HTTP status code.
-
#success? ⇒ Boolean
Check whether the request succeeded.
Constructor Details
#initialize(http_method:, uri:, http_response: nil, status: nil, headers: nil, body: nil) ⇒ Response
Summarize a response
Public, so that an on_response hook can be tested with a summary built from the status, headers, and body of a response, or from a Net::HTTP response, as the client builds one for each response it reads.
93 94 95 96 97 98 99 |
# File 'x-core/lib/x/core/response.rb', line 93 def initialize(http_method:, uri:, http_response: nil, status: nil, headers: nil, body: nil) @http_method = http_method.downcase.to_sym @uri = uri @http_response = BuiltResponse.of(http_response, status:, headers:, body: (body if http_response.nil?)) @body = body.dup&.force_encoding(Encoding::UTF_8) @parsed = ParsedBody.new end |
Instance Attribute Details
#http_method ⇒ Symbol (readonly)
The HTTP method of the request
46 47 48 |
# File 'x-core/lib/x/core/response.rb', line 46 def http_method @http_method end |
#http_response ⇒ Net::HTTPResponse (readonly)
The response itself, as the client received it
It is an escape hatch, for what a summary does not read: the status is #status, the headers are #headers, and the body is #body. It is the response of the transport the client sent the request with, a Net::HTTPResponse today, or the one built of the status, headers, and body the summary was given. Its class is not covered by the compatibility promise of 1.x: a later release of 1.x may send its requests with another library, whose response this then returns.
67 68 69 |
# File 'x-core/lib/x/core/response.rb', line 67 def http_response @http_response end |
#uri ⇒ URI::Generic (readonly)
The URI of the request
53 54 55 |
# File 'x-core/lib/x/core/response.rb', line 53 def uri @uri end |
Instance Method Details
#body ⇒ String?
The body summarized: one streamed object, or else the whole body
It is tagged UTF-8, the encoding of the JSON the API sends. A body that is not valid UTF-8 keeps its bytes, so valid_encoding? tells it apart, and scrub replaces what is not UTF-8.
110 |
# File 'x-core/lib/x/core/response.rb', line 110 def body = @body || http_response.body |
#headers ⇒ Hash{String => String}
The headers of the response
The names are lowercase, and a field the API sent more than once is joined with a comma.
|
|
# File 'x-core/lib/x/core/response.rb', line 32
|
#rate_limit ⇒ RateLimit?
The 15-minute rate limit of the endpoint, which nearly every response reports
142 |
# File 'x-core/lib/x/core/response.rb', line 142 def rate_limit = rate_limits.find { |limit| limit.type.eql?(RateLimit::RATE_LIMIT_TYPE) } |
#rate_limits ⇒ Array<RateLimit>
The rate limits the response reports in its headers
134 |
# File 'x-core/lib/x/core/response.rb', line 134 def rate_limits = RateLimit.__send__(:all_from, http_response) |
#resource_count ⇒ Integer
The number of resources the body holds, in data and includes together
169 |
# File 'x-core/lib/x/core/response.rb', line 169 def resource_count = resource_counts.values.sum |
#resource_counts ⇒ Hash{String => Integer}
The number of resources the body holds, as data and as each kind of include
The API bills reads by the resource, but once a UTC day for each, so these count what the response returned, not what X billed for it. The body is parsed once, however many times a summary is asked what it holds, unless the summary was frozen deeply, as Ractor.make_shareable freezes one, before it was first asked, which leaves it nowhere to keep what it parsed. A body whose includes is not an object holds no includes to count.
155 156 157 158 159 160 161 |
# File 'x-core/lib/x/core/response.rb', line 155 def resource_counts body = parsed_body data = body["data"] counts = {"data" => Array.try_convert(data)&.size || [data].compact.size} Hash.try_convert(body["includes"])&.each { |key, resources| counts[key] = Array(resources).size } counts end |
#status ⇒ Integer
The HTTP status code
118 |
# File 'x-core/lib/x/core/response.rb', line 118 def status = Integer(http_response.code) |
#success? ⇒ Boolean
Check whether the request succeeded
126 |
# File 'x-core/lib/x/core/response.rb', line 126 def success? = http_response.is_a?(Net::HTTPSuccess) |