Class: Protocol::HTTP::Body::Readable
- Inherits:
-
Object
- Object
- Protocol::HTTP::Body::Readable
- Defined in:
- lib/protocol/http/body/readable.rb
Overview
Represents a readable input streams.
There are two major modes of operation:
-
Reading chunks using #read (or #each/#join), until the body is empty, or
-
Streaming chunks using #call, which writes chunks to a provided output stream.
In both cases, reading can 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, or the stream will be closed with an error.
At any point, you can use #close to close the stream and release any resources, or #discard to read all remaining data without processing it which may allow the underlying connection to be reused (but can be slower).
Instance Method Summary collapse
-
#as_json ⇒ Object
Convert the body to a hash suitable for serialization.
-
#buffered ⇒ Object
Return a buffered representation of this body.
-
#call(stream) ⇒ Object
Invoke the body with the given stream.
-
#close(error = nil) ⇒ Object
Close the stream immediately.
-
#discard ⇒ Object
Discard the body as efficiently as possible.
-
#each ⇒ Object
Enumerate all chunks until finished, then invoke #close.
-
#empty? ⇒ Boolean
Optimistically determine whether read (may) return any data.
-
#finish ⇒ Object
Read all remaining chunks into a buffered body and close the underlying input.
-
#join ⇒ Object
Read all remaining chunks into a single binary string using ‘#each`.
-
#length ⇒ Object
The total length of the body, if known.
-
#read ⇒ Object
Read the next available chunk.
-
#ready? ⇒ Boolean
Whether calling read will return a chunk of data without blocking.
-
#rewind ⇒ Object
Rewind the stream to the beginning.
-
#rewindable? ⇒ Boolean
Whether the stream can be rewound using #rewind.
- #stream? ⇒ Boolean
-
#to_json ⇒ Object
Convert the body to JSON.
Instance Method Details
#as_json ⇒ Object
Convert the body to a hash suitable for serialization. This won’t include the contents of the body, but will include metadata such as the length, streamability, and readiness, etc.
173 174 175 176 177 178 179 180 181 |
# File 'lib/protocol/http/body/readable.rb', line 173 def as_json(...) { class: self.class.name, length: self.length, stream: self.stream?, ready: self.ready?, empty: self.empty? } end |
#buffered ⇒ Object
Return a buffered representation of this body.
This method must return a buffered body if ‘#rewindable?`.
67 68 69 |
# File 'lib/protocol/http/body/readable.rb', line 67 def buffered nil end |
#call(stream) ⇒ Object
Invoke the body with 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.
Write the body to the given stream.
138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/protocol/http/body/readable.rb', line 138 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 # TODO Should this invoke close_write(error) instead? stream.close end |
#close(error = nil) ⇒ Object
Close the stream immediately. After invoking this method, the stream should be considered closed, and all internal resources should be released.
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.
28 29 |
# File 'lib/protocol/http/body/readable.rb', line 28 def close(error = nil) end |
#discard ⇒ Object
Discard the body as efficiently as possible.
The default implementation simply reads all chunks until the body is empty.
Useful for discarding the body when it is not needed, but preserving the underlying connection.
165 166 167 168 |
# File 'lib/protocol/http/body/readable.rb', line 165 def discard while chunk = self.read end end |
#each ⇒ Object
Enumerate all chunks until finished, then invoke #close.
Closes the stream when finished or if an error occurs.
92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/protocol/http/body/readable.rb', line 92 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 |
#empty? ⇒ Boolean
Optimistically determine whether read (may) return any data.
-
If this returns true, then calling read will definitely return nil.
-
If this returns false, then calling read may return nil.
37 38 39 |
# File 'lib/protocol/http/body/readable.rb', line 37 def empty? false end |
#finish ⇒ Object
Read all remaining chunks into a buffered body and close the underlying input.
155 156 157 158 |
# File 'lib/protocol/http/body/readable.rb', line 155 def finish # Internally, this invokes `self.each` which then invokes `self.close`. Buffered.read(self) end |
#join ⇒ Object
Read all remaining chunks into a single binary string using ‘#each`.
109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/protocol/http/body/readable.rb', line 109 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 |
#length ⇒ Object
The total length of the body, if known.
74 75 76 |
# File 'lib/protocol/http/body/readable.rb', line 74 def length nil end |
#read ⇒ Object
Read the next available chunk.
82 83 84 |
# File 'lib/protocol/http/body/readable.rb', line 82 def read nil end |
#ready? ⇒ Boolean
Whether calling read will return a chunk of data without blocking. We prefer pessimistic implementation, and thus default to ‘false`.
44 45 46 |
# File 'lib/protocol/http/body/readable.rb', line 44 def ready? false end |
#rewind ⇒ Object
Rewind the stream to the beginning.
58 59 60 |
# File 'lib/protocol/http/body/readable.rb', line 58 def rewind false end |
#rewindable? ⇒ Boolean
Whether the stream can be rewound using #rewind.
51 52 53 |
# File 'lib/protocol/http/body/readable.rb', line 51 def rewindable? false end |
#stream? ⇒ Boolean
126 127 128 |
# File 'lib/protocol/http/body/readable.rb', line 126 def stream? false end |
#to_json ⇒ Object
Convert the body to JSON.
186 187 188 |
# File 'lib/protocol/http/body/readable.rb', line 186 def to_json(...) as_json.to_json(...) end |