When processing uploads, Unicorn may expose a StreamInput object under “rack.input“ of the (future) Rack (2.x) environment.
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
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
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
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
# 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
# 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
# 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
# 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.
Generated with the Darkfish Rdoc Generator 1.1.6.