From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=unavailable autolearn_force=no version=3.4.0 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 03E43200D3 for ; Tue, 7 Jun 2016 07:39:11 +0000 (UTC) From: Eric Wong To: yahns-public@yhbt.net Subject: [PATCH 4/5] proxy_pass: more descriptive error messages Date: Tue, 7 Jun 2016 07:39:07 +0000 Message-Id: <20160607073908.31035-5-e@80x24.org> In-Reply-To: <20160607073908.31035-1-e@80x24.org> References: <20160607073908.31035-1-e@80x24.org> List-Id: This should make it easier to figure out where certain errors are coming from and perhaps fix problems with upstreams, too. This helped me track down the problem causing public-inbox WWW component running under Perl v5.20.2 on my Debian jessie system to break and drop connections going through Plack::Middleware::Deflater with gzip: https://public-inbox.org/meta/20160607071401.29325-1-e@80x24.org/ Perl 5.14.2 on Debian wheezy did not detect this problem :x --- lib/yahns/proxy_http_response.rb | 8 ++++++-- lib/yahns/req_res.rb | 6 ++++-- test/test_proxy_pass.rb | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/yahns/proxy_http_response.rb b/lib/yahns/proxy_http_response.rb index 8de5b4f..9867da2 100644 --- a/lib/yahns/proxy_http_response.rb +++ b/lib/yahns/proxy_http_response.rb @@ -53,6 +53,8 @@ def proxy_err_response(code, req_res, exc) logger.error('premature upstream EOF') when Kcar::ParserError logger.error("upstream response error: #{exc.message}") + when String + logger.error(exc) else Yahns::Log.exception(logger, 'upstream error', exc) end @@ -167,7 +169,9 @@ def proxy_read_body(tip, kcar, req_res) return proxy_unbuffer(wbuf) if Yahns::WbufLite === wbuf when nil # EOF # HTTP/1.1 upstream, unexpected premature EOF: - return proxy_err_response(nil, req_res, nil) if len || chunk + msg = "upstream EOF (#{len} bytes left)" if len + msg = 'upstream EOF (chunk)' if chunk + return proxy_err_response(nil, req_res, msg) if msg # HTTP/1.0 upstream: wbuf = proxy_write(wbuf, "0\r\n\r\n".freeze, req_res) if alive @@ -198,7 +202,7 @@ def proxy_read_trailers(kcar, req_res) when :wait_readable return wait_on_upstream(req_res) when nil # premature EOF - return proxy_err_response(nil, req_res, nil) + return proxy_err_response(nil, req_res, 'upstream EOF (trailers)') end # no loop here end wbuf = proxy_write(wbuf, trailer_out(tlr), req_res) diff --git a/lib/yahns/req_res.rb b/lib/yahns/req_res.rb index 9bb8f35..041b908 100644 --- a/lib/yahns/req_res.rb +++ b/lib/yahns/req_res.rb @@ -42,7 +42,8 @@ def yahns_step # yahns event loop entry point # continue looping in middle "case @resbuf" loop when :wait_readable return rv # spurious wakeup - when nil then return c.proxy_err_response(502, self, nil) + when nil + return c.proxy_err_response(502, self, 'upstream EOF (headers)') end # NOT looping here when String # continue reading trickled response headers from upstream @@ -50,7 +51,8 @@ def yahns_step # yahns event loop entry point case rv = kgio_tryread(0x2000, buf) when String then res = req.headers(@hdr, resbuf << rv) and break when :wait_readable then return rv - when nil then return c.proxy_err_response(502, self, nil) + when nil + return c.proxy_err_response(502, self, 'upstream EOF (big headers)') end while true @resbuf = false diff --git a/test/test_proxy_pass.rb b/test/test_proxy_pass.rb index 5dd8058..4c4b53a 100644 --- a/test/test_proxy_pass.rb +++ b/test/test_proxy_pass.rb @@ -485,7 +485,7 @@ def check_truncated_upstream(host, port) assert_equal exp, res errs = File.readlines(@err.path).grep(/\bERROR\b/) assert_equal 1, errs.size - assert_match(/premature upstream EOF/, errs[0]) + assert_match(/upstream EOF/, errs[0]) @err.truncate(0) # truncated headers or no response at all... @@ -501,7 +501,7 @@ def check_truncated_upstream(host, port) s.close errs = File.readlines(@err.path).grep(/\bERROR\b/) assert_equal 1, errs.size - assert_match(/premature upstream EOF/, errs[0]) + assert_match(/upstream EOF/, errs[0]) @err.truncate(0) end end