about summary refs log tree commit homepage
path: root/test
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2015-04-07 03:16:57 +0000
committerEric Wong <e@80x24.org>2015-04-07 06:49:39 +0000
commitaec9f8095070a746ee44b8e85061141b7253c6ce (patch)
tree74cf97dd38406523dc7c4f19aaa56e777472ab10 /test
parentd3e29023d02c52ddbcd06d44eb9baeb3890402f7 (diff)
downloadyahns-aec9f8095070a746ee44b8e85061141b7253c6ce.tar.gz
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.
Diffstat (limited to 'test')
-rw-r--r--test/test_proxy_pass.rb62
1 files changed, 61 insertions, 1 deletions
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