diff options
-rw-r--r-- | lib/yahns/http_response.rb | 2 | ||||
-rw-r--r-- | test/test_server.rb | 48 |
2 files changed, 49 insertions, 1 deletions
diff --git a/lib/yahns/http_response.rb b/lib/yahns/http_response.rb index 1b9478f..8a4bd6a 100644 --- a/lib/yahns/http_response.rb +++ b/lib/yahns/http_response.rb @@ -125,7 +125,7 @@ module Yahns::HttpResponse # :nodoc: buf << kv_str(key, value) when %r{\AConnection\z}i # allow Rack apps to tell us they want to drop the client - alive = !!(value =~ /\bclose\b/i) + alive = false if value =~ /\bclose\b/i when "rack.hijack" hijack = value body = nil # ensure we do not close body diff --git a/test/test_server.rb b/test/test_server.rb index 6b9f00f..f0df475 100644 --- a/test/test_server.rb +++ b/test/test_server.rb @@ -743,4 +743,52 @@ class TestServer < Testcase tmp.close! quit_wait(pid) end + + def test_app_controls_close + err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1] + pid = mkserver(cfg) do + cfg.instance_eval do + ru = lambda { |env| + h = { 'Content-Length' => '2' } + if env["PATH_INFO"] =~ %r{\A/(.+)} + h["Connection"] = $1 + end + [ 200, h, ['HI'] ] + } + app(:rack, ru) { listen "#{host}:#{port}" } + stderr_path err.path + end + end + c = get_tcp_client(host, port) + + # normal response + c.write "GET /keep-alive HTTP/1.1\r\nHost: example.com\r\n\r\n" + buf = "" + Timeout.timeout(30) do + buf << c.readpartial(4096) until buf =~ /HI\z/ + end + assert_match %r{^Connection: keep-alive}, buf + assert_raises(Errno::EAGAIN,IO::WaitReadable) { c.read_nonblock(666) } + + # we allow whatever in the response, but don't send it + c.write "GET /whatever HTTP/1.1\r\nHost: example.com\r\n\r\n" + buf = "" + Timeout.timeout(30) do + buf << c.readpartial(4096) until buf =~ /HI\z/ + end + assert_match %r{^Connection: keep-alive}, buf + assert_raises(Errno::EAGAIN,IO::WaitReadable) { c.read_nonblock(666) } + + c.write "GET /close HTTP/1.1\r\nHost: example.com\r\n\r\n" + buf = "" + Timeout.timeout(30) do + buf << c.readpartial(4096) until buf =~ /HI\z/ + end + assert_match %r{^Connection: close}, buf + assert_equal c, IO.select([c], nil, nil, 30)[0][0] + assert_raises(EOFError) { c.readpartial(666) } + c.close + ensure + quit_wait(pid) + end end |