class Protocol::HTTP::Body::Readable
If you don’t want to read from a stream, and instead want to close it immediately, you can call ‘close` on the body. If the body is already completely consumed, `close` will do nothing, but if there is still data to be read, it will cause the underlying stream to be reset (and possibly closed).
Reading can also fail, for example if the body represents a streaming upload, and the connection is lost. In this case, `#read` will raise some kind of error.
In general, you read chunks of data from a body until it is empty and returns `nil`. Upon reading `nil`, the body is considered consumed and should not be read from again.
Typically, you’d override ‘#read` to return chunks of data.
Represents a readable input streams.
def as_json(...)
def as_json(...) { class: self.class.name, length: self.length, stream: self.stream?, ready: self.ready?, empty: self.empty? } end
def buffered
This method must return a buffered body if `#rewindable?`.
Return a buffered representation of this body.
def buffered nil end
def call(stream)
@parameter stream [IO | Object] An `IO`-like object that responds to `#read`, `#write` and `#flush`.
Write the body to the given stream.
The default implementation simply writes each chunk to the stream. If the body is not ready, it will be flushed after each chunk. Closes the stream when finished or if an error occurs.
Invoke the body with the given stream.
def call(stream) self.each do |chunk| stream.write(chunk) # Flush the stream unless we are immediately expecting more data: unless self.ready? stream.flush end end ensure stream.close end
def close(error = nil)
If an error occured while handling the output, it can be passed as an argument. This may be propagated to the client, for example the client may be informed that the stream was not fully read correctly.
Close the stream immediately. After invoking this method, the stream should be considered closed, and all internal resources should be released.
def close(error = nil) end
def discard
The default implementation simply reads all chunks until the body is empty.
Discard the body as efficiently as possible.
def discard while chunk = self.read end end
def each
@yields {|chunk| ...} The block to call with each chunk of data.
Closes the stream when finished or if an error occurs.
Enumerate all chunks until finished, then invoke `#close`.
def each return to_enum unless block_given? begin while chunk = self.read yield chunk end rescue => error raise ensure self.close(error) end end
def empty?
If this returns true, then calling read will definitely return nil.
Optimistically determine whether read (may) return any data.
def empty? false end
def finish
Read all remaining chunks into a buffered body and close the underlying input.
def finish # Internally, this invokes `self.each` which then invokes `self.close`. Buffered.read(self) end
def join
Read all remaining chunks into a single binary string using `#each`.
def join buffer = String.new.force_encoding(Encoding::BINARY) self.each do |chunk| buffer << chunk end if buffer.empty? return nil else return buffer end end
def length
The total length of the body, if known.
def length nil end
def read
@returns [String | Nil] The chunk of data, or `nil` if the stream has finished.
Read the next available chunk.
def read nil end
def ready?
-
(Boolean)
-
def ready? false end
def rewind
Rewind the stream to the beginning.
def rewind false end
def rewindable?
def rewindable? false end
def stream?
def stream? false end
def to_json(...)
def to_json(...) as_json.to_json(...) end