diff options
Diffstat (limited to 'lib/yahns/proxy_http_response.rb')
-rw-r--r-- | lib/yahns/proxy_http_response.rb | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/lib/yahns/proxy_http_response.rb b/lib/yahns/proxy_http_response.rb index c8a2a42..c5e7be5 100644 --- a/lib/yahns/proxy_http_response.rb +++ b/lib/yahns/proxy_http_response.rb @@ -43,7 +43,12 @@ module Yahns::HttpResponse # :nodoc: Rack::Utils::HTTP_STATUS_CODES[code]}\r\n\r\n") rescue nil shutdown rescue nil - req_res.shutdown rescue nil + @input = @input.close if @input + + # this is safe ONLY because we are in an :ignore state after + # Fdmap#forget when we got hijacked: + close + nil # signal close of req_res from yahns_step in yahns/proxy_pass.rb ensure wbuf.wbuf_abort if wbuf @@ -56,6 +61,7 @@ module Yahns::HttpResponse # :nodoc: :wait_readable # self remains in :ignore, wait on upstream end + # start streaming the response once upstream is done sending headers to us. # returns :wait_readable if we need to read more from req_res # returns :ignore if we yield control to the client(self) # returns nil if completely done @@ -101,7 +107,6 @@ module Yahns::HttpResponse # :nodoc: # but the backend does not terminate properly if alive && ! term && (env['HTTP_VERSION'] == 'HTTP/1.1'.freeze) res << "Transfer-Encoding: chunked\r\n".freeze - alive = true end res << (alive ? "Connection: keep-alive\r\n\r\n".freeze : "Connection: close\r\n\r\n".freeze) @@ -178,9 +183,9 @@ module Yahns::HttpResponse # :nodoc: end end - return proxy_busy_mod_done(alive) unless wbuf - req_res.resbuf = wbuf - proxy_busy_mod_blocked(wbuf, wbuf.busy) + # all done reading response from upstream, req_res will be discarded + # when we return nil: + wbuf ? proxy_busy_mod_blocked(wbuf, wbuf.busy) : proxy_busy_mod_done(alive) rescue => e proxy_err_response(502, req_res, e, wbuf) end @@ -248,7 +253,7 @@ module Yahns::HttpResponse # :nodoc: end busy = wbuf.busy and return proxy_busy_mod_blocked(wbuf, busy) - proxy_busy_mod_done(wbuf.wbuf_persist) # returns nil + proxy_busy_mod_done(wbuf.wbuf_persist) # returns nil to close req_res end def proxy_wait_next(qflags) @@ -289,23 +294,23 @@ module Yahns::HttpResponse # :nodoc: when :close then close end - nil # close the req_res, too + nil # signal close for ReqRes#yahns_step end def proxy_busy_mod_blocked(wbuf, busy) - q = Thread.current[:yahns_queue] # we are completely done reading and buffering the upstream response, # but have not completely written the response to the client, # yield control to the client socket: @state = wbuf - case busy - when :wait_readable then q.queue_mod(self, Yahns::Queue::QEV_RD) - when :wait_writable then q.queue_mod(self, Yahns::Queue::QEV_WR) - else - abort "BUG: invalid wbuf.busy: #{busy.inspect}" - end - # no touching self after queue_mod - :ignore + proxy_wait_next(case busy + when :wait_readable then Yahns::Queue::QEV_RD + when :wait_writable then Yahns::Queue::QEV_WR + else + abort "BUG: invalid wbuf.busy: #{busy.inspect}" + end) + # no touching self after proxy_wait_next, we may be running + # HttpClient#yahns_step in a different thread at this point + nil # signal close for ReqRes#yahns_step end # n.b.: we can use String#size for optimized dispatch under YARV instead |