yahns Ruby server user/dev discussion
 help / color / Atom feed
From: Eric Wong <e@80x24.org>
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> (raw)
In-Reply-To: <20160607073908.31035-1-e@80x24.org>

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

  parent reply index

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-07  7:39 [PATCH \0/5] another round of proxy-related bugfixes! Eric Wong
2016-06-07  7:39 ` [PATCH 1/5] test_proxy_pass_no_buffering: fix racy test Eric Wong
2016-06-07  7:39 ` [PATCH 2/5] queue_*: check for closed IO objects Eric Wong
2016-06-07  7:39 ` [PATCH 3/5] cleanup graceful shutdown handling Eric Wong
2016-06-07  7:39 ` Eric Wong [this message]
2016-06-07  7:39 ` [PATCH 5/5] proxy_pass: fix HTTP/1.0 backends on EOF w/o buffering Eric Wong

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://yhbt.net/yahns/README

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160607073908.31035-5-e@80x24.org \
    --to=e@80x24.org \
    --cc=yahns-public@yhbt.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

yahns Ruby server user/dev discussion

Archives are clonable:
	git clone --mirror https://yhbt.net/yahns-public
	git clone --mirror http://ou63pmih66umazou.onion/yahns-public

Example config snippet for mirrors

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.lang.ruby.yahns
	nntp://ou63pmih66umazou.onion/inbox.comp.lang.ruby.yahns

 note: .onion URLs require Tor: https://www.torproject.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox