Class: X::StreamResponse
- Inherits:
-
Object
- Object
- X::StreamResponse
- Includes:
- ResponseHeaders
- Defined in:
- x-core/lib/x/core/stream_response.rb
Overview
The response of a request whose body is read as it arrives, which Client#get_stream passes to its block
It is passed to the block before its body is read, so it reads the status and headers the API answered with, and the block reads the body with #read_body, for as long as it likes. It is x-core's own, rather than the response of the library the client sends its requests with, so that a block written for one release of 1.x reads the response of every other, whatever sends the request.
Instance Attribute Summary collapse
-
#http_response ⇒ Net::HTTPResponse
readonly
The response itself, as the client received it, with its body not yet read.
-
#uri ⇒ URI::Generic
readonly
The URI of the request.
Instance Method Summary collapse
-
#headers ⇒ Hash{String => String}
The headers of the response.
-
#rate_limit ⇒ RateLimit?
The 15-minute rate limit of the endpoint.
-
#rate_limits ⇒ Array<RateLimit>
The rate limits the response reports in its headers.
-
#read_body {|chunk| ... } ⇒ String?
Read the body, a chunk at a time as it arrives, or whole.
-
#status ⇒ Integer
The HTTP status code.
Instance Attribute Details
#http_response ⇒ Net::HTTPResponse (readonly)
The response itself, as the client received it, with its body not yet read
It is an escape hatch, for what this does not read: the status is #status, the headers are #headers, and the body is read with #read_body. It is the response of the transport the client sends its requests with, a Net::HTTPResponse today, and 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. A body read from it, rather than with #read_body, raises the errors of its socket as they are, rather than as a NetworkError, which Client#get_stream raises as the block's own, and is not known to #read_body, which counts the reads of its own alone: once the body was read from it, in part or whole, #read_body reads what is left of it, returns the body it read whole, or raises an Error for a body it left none of.
99 100 101 |
# File 'x-core/lib/x/core/stream_response.rb', line 99 def http_response @http_response end |
#uri ⇒ URI::Generic (readonly)
The URI of the request
82 83 84 |
# File 'x-core/lib/x/core/stream_response.rb', line 82 def uri @uri end |
Instance Method Details
#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/stream_response.rb', line 68
|
#rate_limit ⇒ RateLimit?
The 15-minute rate limit of the endpoint
For a stream, it counts the connections that may be opened in the window.
143 |
# File 'x-core/lib/x/core/stream_response.rb', line 143 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
133 |
# File 'x-core/lib/x/core/stream_response.rb', line 133 def rate_limits = RateLimit.__send__(:all_from, http_response) |
#read_body {|chunk| ... } ⇒ String?
Read the body, a chunk at a time as it arrives, or whole
Given a block, each chunk of the body is passed to it as it arrives, until the body ends, which the body of a stream does only when its connection closes. A chunk is whatever arrived, in binary, since it may end within a line, or within a character, which no encoding but binary reads half of. Without a block, the body is read to its end, and returned whole, tagged UTF-8, the encoding of the JSON the API sends, as the body of a Response is: 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. A response without a body, such as a 204, has none to return.
The body is read once, inside the block of Client#get_stream, since it is read from a connection that is closed once that block returns. A body read whole, without a block, is returned again by each read without a block that follows, as a String of its own. Any other second read raises an Error that says so, with or without a block, after a read that passed the chunks to a block, even one the block left partway through, with break, throw, or an error, or after a read that failed; so does any read once the block of Client#get_stream has returned. The Error is the caller's, not the socket's, so it is neither a NetworkError nor retried. Only the reads of this method are counted: a body read from #http_response is not known to it, and a read of a body that was read to its end there, a chunk at a time, raises the same Error, for there is none left. A dup or clone of the response reads the same body, so its reads are counted with those of the response, and a response that was frozen is read as any other is. A response that was frozen deeply, as Ractor.make_shareable freezes one on a Ruby before 4.1, which refuses to share the socket of one, is not: its connection is frozen with it, so a read of a body not yet read raises an Error that says so, while a body read whole before is returned again.
An error of the socket the body is read from, such as a connection that dropped, or a read that timed out, raises a NetworkError here, inside the block of Client#get_stream, which may rescue it, and which Client#get_stream raises as it is otherwise. It names the request, and its cause is the error of the socket. An error the block raises is raised as it was, whatever its class.
193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'x-core/lib/x/core/stream_response.rb', line 193 def read_body(&block) raise Error, READ_OUTSIDE_BLOCK if @state.left return whole_body if @state.whole && !block note_read failed = [] #: Array[Exception] body = StreamBody.reading(uri, failed) { transport_body(block, failed) } return if block @state.body = body @state.whole = true whole_body end |
#status ⇒ Integer
The HTTP status code
125 |
# File 'x-core/lib/x/core/stream_response.rb', line 125 def status = Integer(http_response.code) |