From ac8ac8c26de7f49b9e5610ebeb1c4153722fe6ef Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 4 May 2016 03:49:09 +0000 Subject: proxy_pass: simplify proxy_http_response Again, the cost of having extra branches within a loop is probably neglible compared to having bigger bytecode resulting in worse CPU cache performance and increased maintenance overhead for extra code. --- lib/yahns/proxy_http_response.rb | 76 ++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/lib/yahns/proxy_http_response.rb b/lib/yahns/proxy_http_response.rb index 693528f..00915df 100644 --- a/lib/yahns/proxy_http_response.rb +++ b/lib/yahns/proxy_http_response.rb @@ -134,38 +134,45 @@ module Yahns::HttpResponse # :nodoc: tip = tip.empty? ? [] : [ tip ] if have_body - if len = kcar.body_bytes_left + req_res.proxy_trailers = nil # define to avoid uninitialized warnings + chunk = ''.dup if kcar.chunked? + tlr = nil + len = kcar.body_bytes_left - case tmp = tip.shift || req_res.kgio_tryread(0x2000, rbuf) - when String - len = kcar.body_bytes_left -= tmp.size - wbuf = proxy_write(wbuf, tmp, alive) - when nil # premature EOF - return proxy_err_response(nil, req_res, nil, wbuf) - when :wait_readable - return wait_on_upstream(req_res, alive, wbuf) - end until len == 0 - - elsif kcar.chunked? # nasty chunked body - req_res.proxy_trailers = nil # define to avoid warnings for now - buf = ''.dup - case tmp = tip.shift || req_res.kgio_tryread(0x2000, rbuf) - when String - kcar.filter_body(buf, tmp) - wbuf = proxy_write(wbuf, chunk_out(buf), alive) unless buf.empty? - when nil # premature EOF - return proxy_err_response(nil, req_res, nil, wbuf) - when :wait_readable - return wait_on_upstream(req_res, alive, wbuf) - end until kcar.body_eof? + case tmp = tip.shift || req_res.kgio_tryread(0x2000, rbuf) + when String + if len + kcar.body_bytes_left -= tmp.size # progress for body_eof? => true + elsif chunk + kcar.filter_body(chunk, rbuf = tmp) # progress for body_eof? => true + next if chunk.empty? # read req_res.kgio_tryread for more + tmp = chunk_out(chunk) + elsif alive # HTTP/1.0 upstream, HTTP/1.1 client + tmp = chunk_out(tmp) + # else # HTTP/1.0 upstream, HTTP/1.0 client, do nothing + end + wbuf = proxy_write(wbuf, tmp, alive) + chunk.clear if chunk + when nil # EOF + # HTTP/1.1 upstream, unexpected premature EOF: + return proxy_err_response(nil, req_res, nil, wbuf) if len || chunk + + # HTTP/1.0 upstream: + wbuf = proxy_write(wbuf, "0\r\n\r\n".freeze, true) if alive + req_res.shutdown + break + when :wait_readable + return wait_on_upstream(req_res, alive, wbuf) + end until kcar.body_eof? - buf = tmp - req_res.proxy_trailers = [ buf, tlr = [] ] + if chunk + chunk = rbuf + req_res.proxy_trailers = [ chunk, tlr = [] ] rbuf = Thread.current[:yahns_rbuf] = ''.dup - until kcar.trailers(tlr, buf) + until kcar.trailers(tlr, chunk) case rv = req_res.kgio_tryread(0x2000, rbuf) when String - buf << rv + chunk << rv when :wait_readable return wait_on_upstream(req_res, alive, wbuf) when nil # premature EOF @@ -173,21 +180,6 @@ module Yahns::HttpResponse # :nodoc: end # no loop here end wbuf = proxy_write(wbuf, trailer_out(tlr), alive) - - else # no Content-Length or Transfer-Encoding: chunked, wait on EOF! - - case tmp = tip.shift || req_res.kgio_tryread(0x2000, rbuf) - when String - tmp = chunk_out(tmp) if alive - wbuf = proxy_write(wbuf, tmp, alive) - when nil - wbuf = proxy_write(wbuf, "0\r\n\r\n".freeze, true) if alive - req_res.shutdown - break - when :wait_readable - return wait_on_upstream(req_res, alive, wbuf) - end while true - end end -- cgit v1.2.3-24-ge0c7