From e166cfe5e8d648b544b1291ec157bd234a425e21 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 8 Feb 2013 22:45:20 +0000 Subject: hijacking support for Rack 1.5.x users This requires Rack 1.5.x and unicorn 4.6.0 for hijacking support. Older versions of Rack continue to work fine, but we must use unicorn 4.6.0 features to support this. --- t/hijack.ru | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ t/t0800-rack-hijack.sh | 27 ++++++++++++++++++++++++ t/test_isolate.rb | 4 ++-- 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 t/hijack.ru create mode 100755 t/t0800-rack-hijack.sh (limited to 't') diff --git a/t/hijack.ru b/t/hijack.ru new file mode 100644 index 0000000..64c23d7 --- /dev/null +++ b/t/hijack.ru @@ -0,0 +1,56 @@ +use Rack::Lint +use Rack::ContentLength +use Rack::ContentType, "text/plain" +class DieIfUsed + def each + abort "body.each called after response hijack\n" + end + + def close + abort "body.close called after response hijack\n" + end +end +def lazy_close(io) + thr = Thread.new do + # wait and see if Rainbows! accidentally closes us + sleep((ENV["DELAY"] || 10).to_i) + begin + io.close + rescue => e + warn "E: #{e.message} (#{e.class})" + exit!(3) + end + end + at_exit { thr.join } +end + +run lambda { |env| + case env["PATH_INFO"] + when "/hijack_req" + if env["rack.hijack?"] + io = env["rack.hijack"].call + if io.respond_to?(:read_nonblock) && + env["rack.hijack_io"].respond_to?(:read_nonblock) + + # exercise both, since we Rack::Lint may use different objects + env["rack.hijack_io"].write("HTTP/1.0 200 OK\r\n\r\n") + io.write("request.hijacked") + lazy_close(io) + return [ 500, {}, DieIfUsed.new ] + end + end + [ 500, {}, [ "hijack BAD\n" ] ] + when "/hijack_res" + r = "response.hijacked" + [ 200, + { + "Content-Length" => r.bytesize.to_s, + "rack.hijack" => proc do |io| + io.write(r) + lazy_close(io) + end + }, + DieIfUsed.new + ] + end +} diff --git a/t/t0800-rack-hijack.sh b/t/t0800-rack-hijack.sh new file mode 100755 index 0000000..c8f976d --- /dev/null +++ b/t/t0800-rack-hijack.sh @@ -0,0 +1,27 @@ +#!/bin/sh +. ./test-lib.sh +t_plan 5 "rack.hijack tests (Rack 1.5+ (Rack::VERSION >= [1,2]))" + +t_begin "setup and start" && { + rainbows_setup + rainbows -D -c $unicorn_config hijack.ru + rainbows_wait_start +} + +t_begin "check request hijack" && { + test "xrequest.hijacked" = x"$(curl -sSfv http://$listen/hijack_req)" +} + +t_begin "check response hijack" && { + test "xresponse.hijacked" = x"$(curl -sSfv http://$listen/hijack_res)" +} + +t_begin "killing succeeds" && { + kill $rainbows_pid +} + +t_begin "check stderr" && { + check_stderr +} + +t_done diff --git a/t/test_isolate.rb b/t/test_isolate.rb index 6688b72..6b7fe5a 100644 --- a/t/test_isolate.rb +++ b/t/test_isolate.rb @@ -17,10 +17,10 @@ lock = File.open(__FILE__, "rb") lock.flock(File::LOCK_EX) Isolate.now!(opts) do gem 'kgio', '2.8.0' - gem 'rack', '1.5.1' + gem 'rack', '1.5.2' gem 'kcar', '0.4.0' gem 'raindrops', '0.10.0' - gem 'unicorn', '4.5.0' + gem 'unicorn', '4.6.0' if engine == "ruby" gem 'sendfile', '1.1.0' -- cgit v1.2.3-24-ge0c7