Class: HTTP_Spew::Request
- Inherits:
-
Object
- Object
- HTTP_Spew::Request
- Includes:
- Headers
- Defined in:
- lib/http_spew/request.rb
Overview
This is the base class actually capable of making a normal HTTP request
Direct Known Subclasses
Instance Attribute Summary collapse
-
#error ⇒ Object
Stores any exception that was raised in another thread (e.g. ContentMD5 or InputSpray write drivers).
-
#response ⇒ Object
readonly
Stores the Rack response (a 3-element Array) on success.
-
#to_io ⇒ Object
readonly
May be called by IO.select or for use with IO#wait_*able.
Instance Method Summary collapse
-
#close ⇒ Object
Called by Rack servers after writing a response to a client.
-
#each ⇒ Object
Called by Rack servers to write the response to a client.
-
#initialize(env, input, sock, allow = nil) ⇒ Request
constructor
Creates a new Request based on a Rack
envandinputobject and prepares it for writing tosock. -
#read_response ⇒ Object
returns a 3-element Rack response array on completion returns :wait_readable or :wait_writable if busy Users do not need to call this directly,
resumewill return the result of this. -
#resume ⇒ Object
returns a 3-element Rack response array on completion returns :wait_readable or :wait_writable if busy.
-
#run(timeout) ⇒ Object
returns a 3-element Rack response array on successful completion returns an Exception if one was raised.
- #start_sock(ai) ⇒ Object
-
#too_big! ⇒ Object
:nodoc:.
Methods included from Headers
Constructor Details
#initialize(env, input, sock, allow = nil) ⇒ Request
Creates a new Request based on a Rack env and input object and prepares it for writing to sock. input supercedes env since it may be an alternate IO object (such as one filtered through HTTP_Spew::ContentMD5.
sock may be the String representing an address created with Socket.pack_sockaddr_un or Socket.pack_sockaddr_in, or it may be an actual Socket object
27 28 29 30 31 32 33 34 35 |
# File 'lib/http_spew/request.rb', line 27 def initialize(env, input, sock, allow = nil) @to_io = BasicSocket === sock ? sock : start_sock(sock) if Hash === env @buf, @input = env_to_headers(env, input) else @buf, @input = env, input end @allow = allow end |
Instance Attribute Details
#error ⇒ Object
Stores any exception that was raised in another thread (e.g. ContentMD5 or InputSpray write drivers).
12 13 14 |
# File 'lib/http_spew/request.rb', line 12 def error @error end |
#response ⇒ Object (readonly)
Stores the Rack response (a 3-element Array) on success
15 16 17 |
# File 'lib/http_spew/request.rb', line 15 def response @response end |
#to_io ⇒ Object (readonly)
May be called by IO.select or for use with IO#wait_*able
8 9 10 |
# File 'lib/http_spew/request.rb', line 8 def to_io @to_io end |
Instance Method Details
#close ⇒ Object
Called by Rack servers after writing a response to a client
129 130 131 132 |
# File 'lib/http_spew/request.rb', line 129 def close @to_io.close @input = nil end |
#each ⇒ Object
Called by Rack servers to write the response to a client
107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/http_spew/request.rb', line 107 def each buf = "" case @to_io.read_nonblock(0x4000, buf, exception: false) when :wait_readable @to_io.wait_readable when nil buf.clear return else yield buf end while true end |
#read_response ⇒ Object
returns a 3-element Rack response array on completion returns :wait_readable or :wait_writable if busy Users do not need to call this directly, resume will return the result of this.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/http_spew/request.rb', line 84 def read_response buf = @to_io.recv_nonblock(0x4000, Socket::MSG_PEEK, exception: false) or raise HttpSpew::EOF, "upstream server closed connection", [] String === buf or return buf # Kcar::Parser#headers shortens +buf+ for us hdr_len = buf.size r = Kcar::Parser.new.headers({}, buf) or too_big! if @allow && ! @allow.include?(r[0].to_i) raise HTTP_Spew::UnexpectedResponse, "#{r[0].to_i} not in #{@allow.inspect}", [] end # discard the header data from the socket buffer (hdr_len -= buf.size) > 0 and @to_io.read(hdr_len, buf) @response = r << self end |
#resume ⇒ Object
returns a 3-element Rack response array on completion returns :wait_readable or :wait_writable if busy
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/http_spew/request.rb', line 39 def resume if @buf case w = @to_io.write_nonblock(@buf, exception: false) when :wait_writable, :wait_readable return w else # Integer len = @buf.size if w == len @buf = @input ? @input.read(0x4000, @buf) : nil else tmp = @buf.byteslice(w, len - w) @buf.clear @buf = tmp # loop retry, socket buffer could've expanded end end while @buf end read_response end |
#run(timeout) ⇒ Object
returns a 3-element Rack response array on successful completion returns an Exception if one was raised
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/http_spew/request.rb', line 60 def run(timeout) t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC) buf, @buf = @buf, nil # make inspect nicer @to_io.write(buf) if @input @to_io.write(buf) while @input.read(0x4000, buf) end buf.clear timeout -= (Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0) while :wait_readable == (rv = read_response) && timeout >= 0.0 t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC) @to_io.wait_readable(timeout) if timeout > 0.0 timeout -= (Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0) end rv rescue => e @input.respond_to?(:close) and @input.close rescue nil self.error = e end |
#start_sock(ai) ⇒ Object
134 135 136 137 138 139 140 141 |
# File 'lib/http_spew/request.rb', line 134 def start_sock(ai) ai = Addrinfo.new(ai) unless Addrinfo === ai sock = Socket.new(ai.afamily, :SOCK_STREAM) case sock.connect_nonblock(ai, exception: false) when 0, :wait_writable end sock end |
#too_big! ⇒ Object
:nodoc:
102 103 104 |
# File 'lib/http_spew/request.rb', line 102 def too_big! # :nodoc: raise HTTP_Spew::RequestError.new(self), "response headers too large", [] end |