Class: Unicorn::TeeInput
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
StreamInput
|
|
Instance Chain:
self,
StreamInput
|
|
Inherits: |
Unicorn::StreamInput
|
Defined in: | lib/unicorn/tee_input.rb |
Overview
Acts like tee(1) on an input input to provide a input-like stream while providing rewindable semantics through a File/StringIO backing store. On the first pass, the input is only read on demand so your Rack application can use input notification (upload progress and like). This should fully conform to the Rack::Lint::InputWrapper
specification on the public API. This class is intended to be a strict interpretation of Rack::Lint::InputWrapper
functionality and will not support any deviations from it.
When processing uploads, unicorn exposes a TeeInput
object under “rack.input” of the Rack environment by default.
Class Attribute Summary
-
.client_body_buffer_size
rw
Internal use only
returns the maximum size of request bodies to buffer in memory, amounts larger than this are buffered to the filesystem.
-
.client_body_buffer_size=(bytes)
rw
Internal use only
sets the maximum size of request bodies to buffer in memory, amounts larger than this are buffered to the filesystem.
Class Method Summary
-
.new(socket, request) ⇒ TeeInput
constructor
Internal use only
Initializes a new
TeeInput
object.
StreamInput
- Inherited
.new | Initializes a new |
Instance Attribute Summary
StreamInput
- Inherited
Instance Method Summary
-
#gets ⇒ String?
Reads the next “line” from the I/O stream; lines are separated by the global record separator ($/, typically “n”).
-
#read([length [, buffer ]]) ⇒ String, ...
Reads at most length bytes from the I/O stream, or to the end of file if length is omitted or is nil.
-
#rewind ⇒ 0
Positions the ios pointer to the beginning of input, returns the offset (zero) of the
ios
pointer. -
#size ⇒ Integer
Returns the size of the input.
-
#consume!
private
consumes the stream of the socket.
- #tee(buffer) private
-
#new_tmpio
Internal use only
for
Rack::TempfileReaper
in rack 1.6+.
StreamInput
- Inherited
#each | Executes the block for every “line” in ios, where lines are separated by the global record separator ($/, typically “n”). |
#gets | Reads the next “line” from the I/O stream; lines are separated by the global record separator ($/, typically “n”). |
#read | Reads at most length bytes from the I/O stream, or to the end of file if length is omitted or is nil. |
#eof!, #filter_body, #read_all |
Constructor Details
.new(socket, request) ⇒ TeeInput
Initializes a new TeeInput
object. You normally do not have to call this unless you are writing an HTTP server.
# File 'lib/unicorn/tee_input.rb', line 41
def initialize(socket, request) # :nodoc: @len = request.content_length super @tmp = @len && @len <= @@client_body_buffer_size ? StringIO.new("") : new_tmpio end
Class Attribute Details
.client_body_buffer_size (rw)
returns the maximum size of request bodies to buffer in memory, amounts larger than this are buffered to the filesystem
# File 'lib/unicorn/tee_input.rb', line 28
def self.client_body_buffer_size # :nodoc: @@client_body_buffer_size end
.client_body_buffer_size=(bytes) (rw)
sets the maximum size of request bodies to buffer in memory, amounts larger than this are buffered to the filesystem
# File 'lib/unicorn/tee_input.rb', line 22
def self.client_body_buffer_size=(bytes) # :nodoc: @@client_body_buffer_size = bytes end
Instance Method Details
#consume! (private)
consumes the stream of the socket
# File 'lib/unicorn/tee_input.rb', line 123
def consume! junk = "" nil while read(@@io_chunk_size, junk) end
#gets ⇒ String
?
Reads the next “line” from the I/O stream; lines are separated by the global record separator ($/, typically “n”). A global record separator of nil reads the entire unread contents of ios. Returns nil if called at the end of file. This takes zero arguments for strict Rack::Lint
compatibility, unlike IO#gets
.
# File 'lib/unicorn/tee_input.rb', line 104
def gets @socket ? tee(super) : @tmp.gets end
#new_tmpio
for Rack::TempfileReaper
in rack 1.6+
#read([length [, buffer ]]) ⇒ String
, ...
Reads at most length bytes from the I/O stream, or to the end of file if length is omitted or is nil. length must be a non-negative integer or nil. If the optional buffer argument is present, it must reference a String, which will receive the data.
At end of file, it returns nil or “” depend on length. ios.read() and ios.read(nil) returns “”. ios.read(length [, buffer]) returns nil.
If the Content-Length of the HTTP request is known (as is the common case for POST requests), then ios.read(length [, buffer]) will block until the specified length is read (or it is the last chunk). Otherwise, for uncommon “Transfer-Encoding: chunked” requests, ios.read(length [, buffer]) will return immediately if there is any data and only block when nothing is available (providing IO#readpartial
semantics).
# File 'lib/unicorn/tee_input.rb', line 91
def read(*args) @socket ? tee(super) : @tmp.read(*args) end
#rewind ⇒ 0
Positions the ios pointer to the beginning of input, returns the offset (zero) of the ios
pointer. Subsequent reads will start from the beginning of the previously-buffered input.
#size ⇒ Integer
Returns the size of the input. For requests with a Content-Length header value, this will not read data off the socket and just return the value of the Content-Length header as an Integer.
For Transfer-Encoding:chunked requests, this requires consuming all of the input stream before returning since there’s no other way to determine the size of the request body beforehand.
This method is no longer part of the Rack specification as of Rack 1.2, so its use is not recommended. This method only exists for compatibility with Rack applications designed for Rack 1.1 and earlier. Most applications should only need to call #read with a specified length
in a loop until it returns nil
.
# File 'lib/unicorn/tee_input.rb', line 64
def size @len and return @len pos = @tmp.pos consume! @tmp.pos = pos @len = @tmp.size end
#tee(buffer) (private)
[ GitHub ]# File 'lib/unicorn/tee_input.rb', line 128
def tee(buffer) @tmp.write(buffer) if buffer buffer end