From aec9f8095070a746ee44b8e85061141b7253c6ce Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 7 Apr 2015 03:16:57 +0000 Subject: proxy_pass: preliminary support for passing trailers Rack apps may (through a round-about way) send HTTP trailers to HTTP/1.1 clients, and we need a way to forward those responses through without losing the trailers. --- test/test_proxy_pass.rb | 62 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'test/test_proxy_pass.rb') diff --git a/test/test_proxy_pass.rb b/test/test_proxy_pass.rb index 47fc231..943fb35 100644 --- a/test/test_proxy_pass.rb +++ b/test/test_proxy_pass.rb @@ -53,6 +53,33 @@ class TestProxyPass < Testcase io = env['rack.hijack'].call io.write(TRUNCATE_HEAD) io.close + when '/response-trailer' + h = [ + %w(Content-Type text/pain), + %w(Transfer-Encoding chunked), + %w(Trailer Foo) + ] + b = [ "3\r\n", "hi\n", "\r\n", "0\r\n", "Foo: bar", "\r\n", "\r\n" ] + case env['HTTP_X_TRAILER'] + when 'fast' + b = [ b.join ] + when 'allslow' + def b.each + size.times do |i| + sleep 0.1 + yield self[i] + end + end + when /\Atlrslow(\d+)/ + b.instance_variable_set(:@yahns_sleep_thresh, $1.to_i) + def b.each + size.times do |i| + sleep(0.1) if i > @yahns_sleep_thresh + yield self[i] + end + end + end + [ 200, h, b ] when '/immediate-EOF' env['rack.hijack'].call.close when %r{\A/chunky-slow-(\d+(?:\.\d+)?)\z} @@ -184,7 +211,7 @@ class TestProxyPass < Testcase @srv.close cfg.instance_eval do app(:rack, ProxiedApp.new) do - listen "#{host2}:#{port2}" + listen "#{host2}:#{port2}", rcvbuf: 4096 client_max_body_size nil end stderr_path err.path @@ -192,6 +219,7 @@ class TestProxyPass < Testcase end check_pipelining(host, port) + check_response_trailer(host, port) gplv3 = File.open('COPYING') @@ -434,4 +462,36 @@ class TestProxyPass < Testcase ensure s.close if s end + + def check_response_trailer(host, port) + thrs = [ + "X-Trailer: fast\r\n", + "X-Trailer: allslow\r\n", + "X-Trailer: tlrslow1\r\n", + "X-Trailer: tlrslow2\r\n", + "X-Trailer: tlrslow3\r\n", + "X-Trailer: tlrslow4\r\n", + '' + ].map do |x| + Thread.new do + s = TCPSocket.new(host, port) + s.write "GET /response-trailer HTTP/1.1\r\n#{x}" \ + "Host: example.com\r\n\r\n" + res = '' + buf = '' + Timeout.timeout(60) do + until res =~ /Foo: bar\r\n\r\n\z/ + res << s.readpartial(16384, buf) + end + end + assert_match(%r{\r\n0\r\nFoo: bar\r\n\r\n\z}, res) + assert_match(%r{^Trailer: Foo\r\n}, res) + assert_match(%r{^Transfer-Encoding: chunked\r\n}, res) + assert_match(%r{\AHTTP/1\.1 200 OK\r\n}, res) + s.close + :OK + end + end + thrs.each { |t| assert_equal(:OK, t.value) } + end end -- cgit v1.2.3-24-ge0c7