From d3e29023d02c52ddbcd06d44eb9baeb3890402f7 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 4 Apr 2015 00:39:32 +0000 Subject: proxy_pass: more tests for giant headers and truncations We need to ensure more uncommon cases such as gigantic upstream headers and truncated upstream responses are handled properly and predictably. --- test/test_proxy_pass.rb | 62 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/test_proxy_pass.rb b/test/test_proxy_pass.rb index 163a0f7..47fc231 100644 --- a/test/test_proxy_pass.rb +++ b/test/test_proxy_pass.rb @@ -13,6 +13,11 @@ class TestProxyPass < Testcase TRUNCATE_HEAD = "HTTP/1.1 200 OK\r\n" \ "Content-Length: 666\r\n".freeze + # not too big, or kcar will reject + BIG_HEADER = [%w(Content-Type text/plain), %W(Content-Length #{OMFG.size})] + 3000.times { |i| BIG_HEADER << %W(X-#{i} BIG-HEADER!!!!!!!!!!!!!!) } + BIG_HEADER.freeze + class ProxiedApp def call(env) h = [ %w(Content-Length 3), %w(Content-Type text/plain) ] @@ -22,6 +27,11 @@ class TestProxyPass < Testcase when '/giant-body' h = [ %W(Content-Length #{OMFG.size}), %w(Content-Type text/plain) ] [ 200, h, [ OMFG ] ] + when '/big-headers' + [ 200, BIG_HEADER, [ OMFG ] ] + when '/oversize-headers' + 100000.times { |x| h << %W(X-TOOBIG-#{x} #{x}) } + [ 200, h, [ "big" ] ] when %r{\A/slow-headers-(\d+(?:\.\d+)?)\z} delay = $1.to_f io = env['rack.hijack'].call @@ -61,7 +71,12 @@ class TestProxyPass < Testcase [ 200, h, [ "hi\n"] ] end when 'HEAD' - [ 200, h, [] ] + case env['PATH_INFO'] + when '/big-headers' + [ 200, BIG_HEADER, [] ] + else + [ 200, h, [] ] + end when 'PUT' buf = env['rack.input'].read [ 201, { @@ -158,7 +173,7 @@ class TestProxyPass < Testcase @srv2.close cfg.instance_eval do app(:rack, Yahns::ProxyPass.new("http://#{host2}:#{port2}")) do - listen "#{host}:#{port}" + listen "#{host}:#{port}", sndbuf: 16384 client_max_body_size nil end stderr_path err.path @@ -245,6 +260,14 @@ class TestProxyPass < Testcase res = http.request(req) assert_equal OMFG, res.body assert_equal 201, res.code.to_i + + # sometimes upstream feeds kcar too much + req = Net::HTTP::Get.new('/oversize-headers') + res = http.request(req) + errs = File.readlines(@err.path).grep(/ERROR/) + assert_equal 1, errs.size + assert_match %r{upstream response error:}, errs[0] + @err.truncate(0) end # ensure we do not chunk responses back to an HTTP/1.0 client even if @@ -264,6 +287,8 @@ class TestProxyPass < Testcase end end check_truncated_upstream(host, port) + check_slow_giant_body(host, port) + check_slow_read_headers(host, port) ensure gplv3.close if gplv3 quit_wait pid @@ -376,4 +401,37 @@ class TestProxyPass < Testcase @err.truncate(0) end end + + def check_slow_giant_body(host, port) + s = TCPSocket.new(host, port) + s.write "GET /giant-body HTTP/1.0\r\n\r\n" + sleep 0.1 + str = '' + buf = '' + assert_raises(EOFError) { loop { str << s.readpartial(400, buf) } } + h, b = str.split(/\r\n\r\n/, 2) + assert_equal OMFG, b + assert_match %r{\AHTTP/1\.1 200\b}, h + ensure + s.close if s + end + + def check_slow_read_headers(host, port) + s = TCPSocket.new(host, port) + s.write "GET /big-headers HTTP/1.1\r\nHost: example.com\r\n\r\n" + s.write "HEAD /big-headers HTTP/1.0\r\n\r\n" + buf = '' + res = '' + sleep 0.1 + begin + res << s.readpartial(32786, buf) + rescue EOFError + break + end while true + # res = Timeout.timeout(60) { s.read } + assert_match %r{\r\n\r\n\z}, res + assert_match %r{\AHTTP/1\.1 200 OK}, res + ensure + s.close if s + end end -- cgit v1.2.3-24-ge0c7