Parent

Unicorn::StreamInput

When processing uploads, Unicorn may expose a StreamInput object under “rack.input“ of the (future) Rack (2.x) environment.

Public Class Methods

new(socket, request) click to toggle source

Initializes a new StreamInput object. You normally do not have to call this unless you are writing an HTTP server.

    # File lib/unicorn/stream_input.rb, line 13
13:   def initialize(socket, request)
14:     @chunked = request.content_length.nil?
15:     @socket = socket
16:     @parser = request
17:     @buf = request.buf
18:     @rbuf = ''
19:     @bytes_read = 0
20:     filter_body(@rbuf, @buf) unless @buf.empty?
21:   end

Public Instance Methods

each { |line| block } => ios click to toggle source

Executes the block for every ``line’’ in ios, where lines are separated by the global record separator ($/, typically “n“).

     # File lib/unicorn/stream_input.rb, line 96
 96:   def each
 97:     while line = gets
 98:       yield line
 99:     end
100: 
101:     self # Rack does not specify what the return value is here
102:   end
gets => string or nil click to toggle source

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/stream_input.rb, line 74
74:   def gets
75:     sep = $/
76:     if sep.nil?
77:       read_all(rv = '')
78:       return rv.empty? ? nil : rv
79:     end
80:     re = /\A(.*?#{Regexp.escape(sep)})/
81: 
82:     begin
83:       @rbuf.sub!(re, '') and return $1
84:       return @rbuf.empty? ? nil : @rbuf.slice!(0, @rbuf.size) if eof?
85:       @socket.kgio_read(@@io_chunk_size, @buf) or eof!
86:       filter_body(once = '', @buf)
87:       @rbuf << once
88:     end while true
89:   end
read([length [, buffer ]]) => string, buffer, or nil click to toggle source

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/stream_input.rb, line 42
42:   def read(length = nil, rv = '')
43:     if length
44:       if length <= @rbuf.size
45:         length < 0 and raise ArgumentError, "negative length #{length} given"
46:         rv.replace(@rbuf.slice!(0, length))
47:       else
48:         to_read = length - @rbuf.size
49:         rv.replace(@rbuf.slice!(0, @rbuf.size))
50:         until to_read == 0 || eof? || (rv.size > 0 && @chunked)
51:           @socket.kgio_read(to_read, @buf) or eof!
52:           filter_body(@rbuf, @buf)
53:           rv << @rbuf
54:           to_read -= @rbuf.size
55:         end
56:         @rbuf.replace('')
57:       end
58:       rv = nil if rv.empty? && length != 0
59:     else
60:       read_all(rv)
61:     end
62:     rv
63:   end

Private Instance Methods

eof!() click to toggle source
     # File lib/unicorn/stream_input.rb, line 137
137:   def eof!
138:     # in case client only did a premature shutdown(SHUT_WR)
139:     # we do support clients that shutdown(SHUT_WR) after the
140:     # _entire_ request has been sent, and those will not have
141:     # raised EOFError on us.
142:     if @socket
143:       @socket.shutdown
144:       @socket.close
145:     end
146:   ensure
147:     raise Unicorn::ClientShutdown, "bytes_read=#{@bytes_read}", []
148:   end
eof?() click to toggle source
     # File lib/unicorn/stream_input.rb, line 106
106:   def eof?
107:     if @parser.body_eof?
108:       while @chunked && ! @parser.parse
109:         once = @socket.kgio_read(@@io_chunk_size) or eof!
110:         @buf << once
111:       end
112:       @socket = nil
113:       true
114:     else
115:       false
116:     end
117:   end
filter_body(dst, src) click to toggle source
     # File lib/unicorn/stream_input.rb, line 119
119:   def filter_body(dst, src)
120:     rv = @parser.filter_body(dst, src)
121:     @bytes_read += dst.size
122:     rv
123:   end
read_all(dst) click to toggle source
     # File lib/unicorn/stream_input.rb, line 125
125:   def read_all(dst)
126:     dst.replace(@rbuf)
127:     @socket or return
128:     until eof?
129:       @socket.kgio_read(@@io_chunk_size, @buf) or eof!
130:       filter_body(@rbuf, @buf)
131:       dst << @rbuf
132:     end
133:     ensure
134:       @rbuf.replace('')
135:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.