* [PATCH] proxy_pass: attempt to forward premature upstream responses
@ 2015-04-11 0:41 Eric Wong
0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2015-04-11 0:41 UTC (permalink / raw)
To: yahns-public
Upstreams may shut us down while we're writing a request body,
attempt to forward any responses from the upstream back to the
client which may explain the rejection reason for giant uploads.
---
lib/yahns/proxy_pass.rb | 5 +++++
test/test_proxy_pass.rb | 48 +++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/lib/yahns/proxy_pass.rb b/lib/yahns/proxy_pass.rb
index d02bb40..e86e9c9 100644
--- a/lib/yahns/proxy_pass.rb
+++ b/lib/yahns/proxy_pass.rb
@@ -139,6 +139,11 @@ def send_req_body(req)
close_req_body(input)
prepare_wait_readable
end
+ rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ENOTCONN
+ # no more reading off the client socket, just prepare to forward
+ # the rejection response from the upstream (if any)
+ @yahns_client.to_io.shutdown(Socket::SHUT_RD)
+ prepare_wait_readable
end
def prepare_wait_readable
diff --git a/test/test_proxy_pass.rb b/test/test_proxy_pass.rb
index eb866b3..840ad1c 100644
--- a/test/test_proxy_pass.rb
+++ b/test/test_proxy_pass.rb
@@ -141,11 +141,21 @@ def chunky.each
[ 200, h, [] ]
end
when 'PUT'
- buf = env['rack.input'].read
- [ 201, {
- 'Content-Length' => buf.bytesize.to_s,
- 'Content-Type' => 'text/plain',
- }, [ buf ] ]
+ case env['PATH_INFO']
+ when '/forbidden-put'
+ # ignore rack.input
+ [ 403, [ %w(Content-Type text/html), %w(Content-Length 0) ], [] ]
+ when '/forbidden-put-abort'
+ env['rack.hijack'].call.close
+ # should not be seen:
+ [ 123, [ %w(Content-Type text/html), %w(Content-Length 0) ], [] ]
+ else
+ buf = env['rack.input'].read
+ [ 201, {
+ 'Content-Length' => buf.bytesize.to_s,
+ 'Content-Type' => 'text/plain',
+ }, [ buf ] ]
+ end
end
end
end
@@ -249,11 +259,13 @@ def test_proxy_pass
app(:rack, ProxiedApp.new) do
listen "#{host2}:#{port2}"
client_max_body_size nil
+ input_buffering :lazy
end
stderr_path err.path
end
end
+ check_forbidden_put(host, port)
check_eof_body(host, port)
check_pipelining(host, port)
check_response_trailer(host, port)
@@ -560,4 +572,30 @@ def check_eof_body(host, port)
s.close
end
end
+
+ def check_forbidden_put(host, port)
+ to_close = []
+ Timeout.timeout(60) do
+ s = TCPSocket.new(host, port)
+ to_close << s
+ s.write("PUT /forbidden-put HTTP/1.1\r\nHost: example.com\r\n" \
+ "Content-Length: #{OMFG.size}\r\n\r\n")
+ assert_equal OMFG.size, s.write(OMFG),
+ "proxy fully buffers, upstream does not"
+ assert_match %r{\AHTTP/1\.1 403 }, s.readpartial(1024)
+ assert_raises(EOFError) { s.readpartial(1) }
+
+ s = TCPSocket.new(host, port)
+ to_close << s
+ s.write("PUT /forbidden-put-abort HTTP/1.1\r\nHost: example.com\r\n" \
+ "Content-Length: #{OMFG.size}\r\n\r\n")
+ assert_equal OMFG.size, s.write(OMFG),
+ "proxy fully buffers, upstream does not"
+ assert_match %r{\AHTTP/1\.1 502 Bad Gateway}, s.readpartial(1024)
+ assert_raises(EOFError) { s.readpartial(1) }
+ @err.truncate(0)
+ end
+ ensure
+ to_close.each(&:close)
+ end
end
--
EW
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2015-04-11 0:41 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-11 0:41 [PATCH] proxy_pass: attempt to forward premature upstream responses Eric Wong
Code repositories for project(s) associated with this public inbox
https://yhbt.net/yahns.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).