yahns 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Documentation/.gitignore +5 -0
- data/Documentation/GNUmakefile +50 -0
- data/Documentation/yahns-rackup.txt +152 -0
- data/Documentation/yahns.txt +68 -0
- data/Documentation/yahns_config.txt +563 -0
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +14 -7
- data/HACKING +56 -0
- data/INSTALL +8 -0
- data/README +15 -2
- data/Rakefile +2 -2
- data/bin/yahns +1 -2
- data/bin/yahns-rackup +9 -0
- data/examples/yahns_multi.conf.rb +14 -4
- data/examples/yahns_rack_basic.conf.rb +17 -1
- data/extras/README +16 -0
- data/extras/autoindex.rb +151 -0
- data/extras/exec_cgi.rb +108 -0
- data/extras/proxy_pass.rb +210 -0
- data/extras/try_gzip_static.rb +208 -0
- data/lib/yahns.rb +5 -2
- data/lib/yahns/acceptor.rb +64 -22
- data/lib/yahns/cap_input.rb +2 -2
- data/lib/yahns/{client_expire_portable.rb → client_expire_generic.rb} +12 -11
- data/lib/yahns/{client_expire.rb → client_expire_tcpi.rb} +7 -6
- data/lib/yahns/config.rb +107 -22
- data/lib/yahns/daemon.rb +2 -0
- data/lib/yahns/fdmap.rb +28 -9
- data/lib/yahns/http_client.rb +123 -37
- data/lib/yahns/http_context.rb +21 -3
- data/lib/yahns/http_response.rb +80 -19
- data/lib/yahns/log.rb +23 -4
- data/lib/yahns/queue_epoll.rb +20 -9
- data/lib/yahns/queue_quitter.rb +16 -0
- data/lib/yahns/queue_quitter_pipe.rb +24 -0
- data/lib/yahns/rack.rb +0 -1
- data/lib/yahns/rackup_handler.rb +57 -0
- data/lib/yahns/server.rb +189 -59
- data/lib/yahns/server_mp.rb +43 -35
- data/lib/yahns/sigevent_pipe.rb +1 -0
- data/lib/yahns/socket_helper.rb +37 -11
- data/lib/yahns/stream_file.rb +14 -4
- data/lib/yahns/stream_input.rb +13 -7
- data/lib/yahns/tcp_server.rb +7 -0
- data/lib/yahns/tmpio.rb +10 -3
- data/lib/yahns/unix_server.rb +7 -0
- data/lib/yahns/wbuf.rb +19 -2
- data/lib/yahns/wbuf_common.rb +10 -3
- data/lib/yahns/wbuf_str.rb +24 -0
- data/lib/yahns/worker.rb +5 -26
- data/test/helper.rb +15 -5
- data/test/server_helper.rb +37 -1
- data/test/test_bin.rb +17 -8
- data/test/test_buffer_tmpdir.rb +103 -0
- data/test/test_client_expire.rb +71 -35
- data/test/test_client_max_body_size.rb +5 -13
- data/test/test_config.rb +1 -1
- data/test/test_expect_100.rb +176 -0
- data/test/test_extras_autoindex.rb +53 -0
- data/test/test_extras_exec_cgi.rb +81 -0
- data/test/test_extras_exec_cgi.sh +35 -0
- data/test/test_extras_try_gzip_static.rb +177 -0
- data/test/test_input.rb +128 -0
- data/test/test_mt_accept.rb +48 -0
- data/test/test_output_buffering.rb +90 -63
- data/test/test_rack.rb +1 -1
- data/test/test_rack_hijack.rb +2 -6
- data/test/test_reopen_logs.rb +2 -8
- data/test/test_serve_static.rb +104 -8
- data/test/test_server.rb +448 -73
- data/test/test_stream_file.rb +1 -1
- data/test/test_unix_socket.rb +72 -0
- data/test/test_wbuf.rb +20 -17
- data/yahns.gemspec +3 -0
- metadata +57 -5
data/test/test_input.rb
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
|
+
require_relative 'server_helper'
|
|
4
|
+
require 'digest/md5'
|
|
5
|
+
|
|
6
|
+
class TestInput < Testcase
|
|
7
|
+
ENV["N"].to_i > 1 and parallelize_me!
|
|
8
|
+
include ServerHelper
|
|
9
|
+
alias setup server_helper_setup
|
|
10
|
+
alias teardown server_helper_teardown
|
|
11
|
+
|
|
12
|
+
MD5 = lambda do |e|
|
|
13
|
+
input = e["rack.input"]
|
|
14
|
+
buf = ""
|
|
15
|
+
md5 = Digest::MD5.new
|
|
16
|
+
while input.read(16384, buf)
|
|
17
|
+
md5 << buf
|
|
18
|
+
end
|
|
19
|
+
body = md5.hexdigest
|
|
20
|
+
h = { "Content-Length" => body.size.to_s, "Content-Type" => 'text/plain' }
|
|
21
|
+
[ 200, h, [body] ]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_input_timeout_lazybuffer
|
|
25
|
+
stream_input_timeout(:lazy)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_input_timeout_nobuffer
|
|
29
|
+
stream_input_timeout(false)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def stream_input_timeout(ibtype)
|
|
33
|
+
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
|
34
|
+
cfg.instance_eval do
|
|
35
|
+
GTL.synchronize do
|
|
36
|
+
app(:rack, MD5) do
|
|
37
|
+
listen "#{host}:#{port}"
|
|
38
|
+
input_buffering ibtype
|
|
39
|
+
client_timeout 1
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
stderr_path err.path
|
|
43
|
+
end
|
|
44
|
+
pid = mkserver(cfg)
|
|
45
|
+
c = get_tcp_client(host, port)
|
|
46
|
+
c.write "PUT / HTTP/1.1\r\nContent-Length: 666\r\n\r\n"
|
|
47
|
+
assert_equal c, c.wait(6)
|
|
48
|
+
Timeout.timeout(30) { assert_match %r{HTTP/1\.1 408 }, c.read }
|
|
49
|
+
c.close
|
|
50
|
+
ensure
|
|
51
|
+
quit_wait(pid)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def input_server(ru, ibtype)
|
|
55
|
+
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
|
56
|
+
cfg.instance_eval do
|
|
57
|
+
GTL.synchronize do
|
|
58
|
+
app(:rack, ru) { listen "#{host}:#{port}"; input_buffering ibtype }
|
|
59
|
+
end
|
|
60
|
+
stderr_path err.path
|
|
61
|
+
end
|
|
62
|
+
pid = mkserver(cfg)
|
|
63
|
+
[ host, port, pid ]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_read_negative_lazy; _read_neg(:lazy); end
|
|
67
|
+
def test_read_negative_nobuffer; _read_neg(false); end
|
|
68
|
+
|
|
69
|
+
def _read_neg(ibtype)
|
|
70
|
+
ru = lambda do |env|
|
|
71
|
+
rv = []
|
|
72
|
+
input = env["rack.input"]
|
|
73
|
+
begin
|
|
74
|
+
input.read(-1)
|
|
75
|
+
rescue => e
|
|
76
|
+
rv << e.class.to_s
|
|
77
|
+
end
|
|
78
|
+
rv << input.read
|
|
79
|
+
rv << input.read(1).nil?
|
|
80
|
+
rv = rv.join(",")
|
|
81
|
+
h = { "Content-Length" => rv.size.to_s }
|
|
82
|
+
[ 200, h, [ rv ] ]
|
|
83
|
+
end
|
|
84
|
+
host, port, pid = input_server(ru, ibtype)
|
|
85
|
+
c = get_tcp_client(host, port)
|
|
86
|
+
c.write "PUT / HTTP/1.0\r\nContent-Length: 5\r\n\r\nhello"
|
|
87
|
+
assert_equal c, c.wait(30)
|
|
88
|
+
head, body = c.read.split(/\r\n\r\n/)
|
|
89
|
+
assert_match %r{ 200 OK}, head
|
|
90
|
+
exc, full, final = body.split(/,/)
|
|
91
|
+
assert_equal "hello", full
|
|
92
|
+
assert_equal "ArgumentError", exc
|
|
93
|
+
assert_equal true.to_s, final
|
|
94
|
+
c.close
|
|
95
|
+
ensure
|
|
96
|
+
quit_wait(pid)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_gets_lazy; _gets(:lazy); end
|
|
100
|
+
def test_gets_nobuffer; _gets(false); end
|
|
101
|
+
|
|
102
|
+
def _gets(ibtype)
|
|
103
|
+
in_join = lambda do |input|
|
|
104
|
+
rv = []
|
|
105
|
+
while line = input.gets
|
|
106
|
+
rv << line
|
|
107
|
+
end
|
|
108
|
+
rv.join(",")
|
|
109
|
+
end
|
|
110
|
+
ru = lambda do |env|
|
|
111
|
+
rv = in_join.call(env["rack.input"])
|
|
112
|
+
h = { "Content-Length" => rv.size.to_s }
|
|
113
|
+
[ 200, h, [ rv ] ]
|
|
114
|
+
end
|
|
115
|
+
host, port, pid = input_server(ru, ibtype)
|
|
116
|
+
c = get_tcp_client(host, port)
|
|
117
|
+
buf = "a\nb\n\n"
|
|
118
|
+
c.write "PUT / HTTP/1.0\r\nContent-Length: 5\r\n\r\n#{buf}"
|
|
119
|
+
assert_equal c, c.wait(30)
|
|
120
|
+
head, body = c.read.split(/\r\n\r\n/)
|
|
121
|
+
assert_match %r{ 200 OK}, head
|
|
122
|
+
expect = in_join.call(StringIO.new(buf))
|
|
123
|
+
assert_equal expect, body
|
|
124
|
+
c.close
|
|
125
|
+
ensure
|
|
126
|
+
quit_wait(pid)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
|
+
require_relative 'server_helper'
|
|
4
|
+
require 'rack/lobster'
|
|
5
|
+
|
|
6
|
+
class TestMtAccept < Testcase
|
|
7
|
+
ENV["N"].to_i > 1 and parallelize_me!
|
|
8
|
+
include ServerHelper
|
|
9
|
+
alias setup server_helper_setup
|
|
10
|
+
alias teardown server_helper_teardown
|
|
11
|
+
|
|
12
|
+
def test_mt_accept
|
|
13
|
+
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
|
14
|
+
opts = { threads: 1 }
|
|
15
|
+
cfg.instance_eval do
|
|
16
|
+
GTL.synchronize do
|
|
17
|
+
app(:rack, Rack::Lobster.new) { listen "#{host}:#{port}", threads: 1 }
|
|
18
|
+
end
|
|
19
|
+
stderr_path err.path
|
|
20
|
+
end
|
|
21
|
+
pid = mkserver(cfg)
|
|
22
|
+
Net::HTTP.start(host, port) do |http|
|
|
23
|
+
assert_equal 200, http.request(Net::HTTP::Get.new("/")).code.to_i
|
|
24
|
+
end
|
|
25
|
+
orig_count = Dir["/proc/#{pid}/task/*"].size
|
|
26
|
+
quit_wait(pid)
|
|
27
|
+
|
|
28
|
+
cfg = Yahns::Config.new
|
|
29
|
+
opts = { threads: 1 }
|
|
30
|
+
cfg.instance_eval do
|
|
31
|
+
GTL.synchronize do
|
|
32
|
+
app(:rack, Rack::Lobster.new) { listen "#{host}:#{port}", threads: 2 }
|
|
33
|
+
end
|
|
34
|
+
stderr_path err.path
|
|
35
|
+
end
|
|
36
|
+
pid = mkserver(cfg)
|
|
37
|
+
Net::HTTP.start(host, port) do |http|
|
|
38
|
+
assert_equal 200, http.request(Net::HTTP::Get.new("/")).code.to_i
|
|
39
|
+
end
|
|
40
|
+
Timeout.timeout(30) do
|
|
41
|
+
begin
|
|
42
|
+
new_count = Dir["/proc/#{pid}/task/*"].size
|
|
43
|
+
end until new_count == (orig_count + 1) && sleep(0.01)
|
|
44
|
+
end
|
|
45
|
+
ensure
|
|
46
|
+
quit_wait(pid)
|
|
47
|
+
end
|
|
48
|
+
end if RUBY_PLATFORM =~ /linux/ && File.directory?("/proc")
|
|
@@ -5,7 +5,7 @@ require 'digest/md5'
|
|
|
5
5
|
require 'rack/file'
|
|
6
6
|
|
|
7
7
|
class TestOutputBuffering < Testcase
|
|
8
|
-
parallelize_me!
|
|
8
|
+
ENV["N"].to_i > 1 and parallelize_me!
|
|
9
9
|
include ServerHelper
|
|
10
10
|
alias setup server_helper_setup
|
|
11
11
|
alias teardown server_helper_teardown
|
|
@@ -41,7 +41,7 @@ class TestOutputBuffering < Testcase
|
|
|
41
41
|
output_buffer(true, :http09)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def output_buffer(btype, check_type
|
|
44
|
+
def output_buffer(btype, check_type)
|
|
45
45
|
err = @err
|
|
46
46
|
cfg = Yahns::Config.new
|
|
47
47
|
host, port = @srv.addr[3], @srv.addr[1]
|
|
@@ -58,54 +58,47 @@ class TestOutputBuffering < Testcase
|
|
|
58
58
|
end
|
|
59
59
|
logger(Logger.new(err.path))
|
|
60
60
|
end
|
|
61
|
-
|
|
62
|
-
pid = fork do
|
|
63
|
-
ENV["YAHNS_FD"] = @srv.fileno.to_s
|
|
64
|
-
srv.start.join
|
|
65
|
-
end
|
|
61
|
+
pid = mkserver(cfg)
|
|
66
62
|
|
|
67
63
|
case check_type
|
|
68
64
|
when :curl
|
|
69
|
-
# curl is faster for piping gigantic wads of data than Net::HTTP
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
assert_equal MD5.value,
|
|
65
|
+
# curl is faster for piping gigantic wads of data than Net::HTTP,
|
|
66
|
+
# and we need to be able to throttle a bit to force output buffering
|
|
67
|
+
c = IO.popen("curl -N -sSf http://#{host}:#{port}/")
|
|
68
|
+
wait_for_full(c)
|
|
69
|
+
dig, nr = md5sum(c)
|
|
70
|
+
c.close
|
|
71
|
+
assert_equal MD5.value, dig.hexdigest
|
|
76
72
|
when :http09
|
|
77
73
|
# HTTP/0.9
|
|
78
|
-
c =
|
|
74
|
+
c = get_tcp_client(host, port)
|
|
79
75
|
c.write("GET /\r\n\r\n")
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
md5pid = Process.spawn("md5sum", :in => md5in[0], :out => md5out[1])
|
|
84
|
-
md5in[0].close
|
|
85
|
-
md5out[1].close
|
|
86
|
-
assert_equal(NR * RAND.size, IO.copy_stream(c, md5in[1]))
|
|
76
|
+
wait_for_full(c)
|
|
77
|
+
dig, nr = md5sum(c)
|
|
78
|
+
assert_equal(NR * RAND.size, nr)
|
|
87
79
|
c.shutdown
|
|
88
80
|
c.close
|
|
89
|
-
|
|
90
|
-
_, status = Timeout.timeout(10) { Process.waitpid2(md5pid) }
|
|
91
|
-
assert status.success?, status.inspect
|
|
92
|
-
md5 = md5out[0].read
|
|
93
|
-
(md5 =~ /([a-f0-9]{32})/i) or raise "bad md5: #{md5.inspect}"
|
|
94
|
-
md5 = $1
|
|
95
|
-
assert_equal MD5.value, md5
|
|
96
|
-
md5out[0].close
|
|
81
|
+
assert_equal MD5.value, dig.hexdigest
|
|
97
82
|
else
|
|
98
83
|
raise "TESTBUG"
|
|
99
84
|
end
|
|
100
|
-
rescue => e
|
|
101
|
-
Yahns::Log.exception(Logger.new($stderr), "test", e)
|
|
102
|
-
raise
|
|
103
85
|
ensure
|
|
104
86
|
quit_wait(pid)
|
|
105
87
|
end
|
|
106
88
|
|
|
89
|
+
def md5sum(c)
|
|
90
|
+
dig = Digest::MD5.new
|
|
91
|
+
buf = ""
|
|
92
|
+
nr = 0
|
|
93
|
+
while c.read(8192, buf)
|
|
94
|
+
dig << buf
|
|
95
|
+
nr += buf.bytesize
|
|
96
|
+
end
|
|
97
|
+
[ dig, nr ]
|
|
98
|
+
end
|
|
99
|
+
|
|
107
100
|
class BigHeader
|
|
108
|
-
A = "A" *
|
|
101
|
+
A = "A" * 8192
|
|
109
102
|
def initialize(h)
|
|
110
103
|
@h = h
|
|
111
104
|
end
|
|
@@ -157,20 +150,14 @@ class TestOutputBuffering < Testcase
|
|
|
157
150
|
end
|
|
158
151
|
logger(Logger.new(err.path))
|
|
159
152
|
end
|
|
160
|
-
|
|
161
|
-
pid = fork do
|
|
162
|
-
ENV["YAHNS_FD"] = @srv.fileno.to_s
|
|
163
|
-
srv.start.join
|
|
164
|
-
end
|
|
153
|
+
pid = mkserver(cfg)
|
|
165
154
|
threads = []
|
|
166
155
|
|
|
167
156
|
# start with just a big header
|
|
168
157
|
threads << Thread.new do
|
|
169
|
-
c =
|
|
158
|
+
c = get_tcp_client(host, port)
|
|
170
159
|
c.write "GET / HTTP/1.0\r\n\r\n"
|
|
171
|
-
|
|
172
|
-
sleep 1
|
|
173
|
-
end while c.nread == 0
|
|
160
|
+
wait_for_full(c)
|
|
174
161
|
nr = 0
|
|
175
162
|
last = nil
|
|
176
163
|
c.each_line do |line|
|
|
@@ -186,11 +173,9 @@ class TestOutputBuffering < Testcase
|
|
|
186
173
|
end
|
|
187
174
|
|
|
188
175
|
threads << Thread.new do
|
|
189
|
-
c =
|
|
176
|
+
c = get_tcp_client(host, port)
|
|
190
177
|
c.write "GET /COPYING HTTP/1.0\r\n\r\n"
|
|
191
|
-
|
|
192
|
-
sleep 1
|
|
193
|
-
end while c.nread == 0
|
|
178
|
+
wait_for_full(c)
|
|
194
179
|
nr = 0
|
|
195
180
|
c.each_line do |line|
|
|
196
181
|
case line
|
|
@@ -205,11 +190,9 @@ class TestOutputBuffering < Testcase
|
|
|
205
190
|
end
|
|
206
191
|
|
|
207
192
|
threads << Thread.new do
|
|
208
|
-
c =
|
|
193
|
+
c = get_tcp_client(host, port)
|
|
209
194
|
c.write "GET /COPYING HTTP/1.0\r\nRange: bytes=5-46\r\n\r\n"
|
|
210
|
-
|
|
211
|
-
sleep 1
|
|
212
|
-
end while c.nread == 0
|
|
195
|
+
wait_for_full(c)
|
|
213
196
|
nr = 0
|
|
214
197
|
c.each_line do |line|
|
|
215
198
|
case line
|
|
@@ -236,6 +219,7 @@ class TestOutputBuffering < Testcase
|
|
|
236
219
|
cfg = Yahns::Config.new
|
|
237
220
|
size = RAND.size * NR
|
|
238
221
|
host, port = @srv.addr[3], @srv.addr[1]
|
|
222
|
+
re = /timeout on :wait_writable after 0\.1s$/
|
|
239
223
|
cfg.instance_eval do
|
|
240
224
|
ru = lambda do |e|
|
|
241
225
|
if e["PATH_INFO"] == "/bh"
|
|
@@ -249,30 +233,34 @@ class TestOutputBuffering < Testcase
|
|
|
249
233
|
app(:rack, ru) do
|
|
250
234
|
listen "#{host}:#{port}"
|
|
251
235
|
output_buffering false
|
|
252
|
-
client_timeout
|
|
236
|
+
client_timeout 0.1
|
|
253
237
|
logger(Logger.new(apperr.path))
|
|
254
238
|
end
|
|
255
239
|
end
|
|
256
240
|
logger(Logger.new(err.path))
|
|
257
241
|
end
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
242
|
+
pid = mkserver(cfg)
|
|
243
|
+
|
|
244
|
+
wait_for_timeout_msg = lambda do
|
|
245
|
+
Timeout.timeout(6) do
|
|
246
|
+
sleep(0.01) until File.readlines(apperr.path).grep(re).size == 2
|
|
247
|
+
end
|
|
262
248
|
end
|
|
263
249
|
threads = []
|
|
264
250
|
threads << Thread.new do
|
|
265
|
-
c =
|
|
251
|
+
c = get_tcp_client(host, port)
|
|
266
252
|
c.write("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
|
|
267
|
-
|
|
253
|
+
wait_for_full(c)
|
|
254
|
+
wait_for_timeout_msg.call
|
|
268
255
|
assert_operator c.nread, :>, 0
|
|
269
256
|
c
|
|
270
257
|
end
|
|
271
258
|
|
|
272
259
|
threads << Thread.new do
|
|
273
|
-
c =
|
|
260
|
+
c = get_tcp_client(host, port)
|
|
274
261
|
c.write("GET /bh HTTP/1.1\r\nHost: example.com\r\n\r\n")
|
|
275
|
-
|
|
262
|
+
wait_for_full(c)
|
|
263
|
+
wait_for_timeout_msg.call
|
|
276
264
|
assert_operator c.nread, :>, 0
|
|
277
265
|
c
|
|
278
266
|
end
|
|
@@ -280,12 +268,51 @@ class TestOutputBuffering < Testcase
|
|
|
280
268
|
assert_operator size, :>, threads[0].value.read.size
|
|
281
269
|
assert_operator size, :>, threads[1].value.read.size
|
|
282
270
|
msg = File.readlines(apperr.path)
|
|
283
|
-
msg = msg.grep(
|
|
271
|
+
msg = msg.grep(re)
|
|
284
272
|
assert_equal 2, msg.size
|
|
285
273
|
threads.each { |t| t.value.close }
|
|
286
274
|
ensure
|
|
287
275
|
apperr.close! if apperr
|
|
288
276
|
quit_wait(pid)
|
|
289
277
|
end
|
|
290
|
-
|
|
291
|
-
|
|
278
|
+
|
|
279
|
+
def test_hijacked
|
|
280
|
+
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
|
281
|
+
cfg.instance_eval do
|
|
282
|
+
ru = lambda do |e|
|
|
283
|
+
h = {
|
|
284
|
+
"Content-Type" => "text/plain",
|
|
285
|
+
"Content-Length" => "4",
|
|
286
|
+
"rack.hijack" => proc { |x| x.write("HIHI"); x.close },
|
|
287
|
+
}
|
|
288
|
+
body = Object.new
|
|
289
|
+
def body.each; abort "body#each should not be used"; end
|
|
290
|
+
[ 200, BigHeader.new(h), body ]
|
|
291
|
+
end
|
|
292
|
+
GTL.synchronize do
|
|
293
|
+
app(:rack, ru) do
|
|
294
|
+
listen "#{host}:#{port}"
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
stderr_path err.path
|
|
298
|
+
end
|
|
299
|
+
pid = mkserver(cfg)
|
|
300
|
+
c = get_tcp_client(host, port)
|
|
301
|
+
c.write "GET / HTTP/1.0\r\n\r\n"
|
|
302
|
+
wait_for_full(c)
|
|
303
|
+
nr = 0
|
|
304
|
+
last = nil
|
|
305
|
+
c.each_line do |line|
|
|
306
|
+
case line
|
|
307
|
+
when %r{\AX-} then nr += 1
|
|
308
|
+
else
|
|
309
|
+
last = line
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
assert_equal NR, nr
|
|
313
|
+
assert_equal "HIHI", last
|
|
314
|
+
c.close
|
|
315
|
+
ensure
|
|
316
|
+
quit_wait(pid)
|
|
317
|
+
end
|
|
318
|
+
end if `which curl 2>/dev/null`.strip =~ /curl/
|
data/test/test_rack.rb
CHANGED
data/test/test_rack_hijack.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require_relative 'server_helper'
|
|
4
4
|
|
|
5
5
|
class TestRackHijack < Testcase
|
|
6
|
-
parallelize_me!
|
|
6
|
+
ENV["N"].to_i > 1 and parallelize_me!
|
|
7
7
|
include ServerHelper
|
|
8
8
|
alias setup server_helper_setup
|
|
9
9
|
alias teardown server_helper_teardown
|
|
@@ -53,11 +53,7 @@ class TestRackHijack < Testcase
|
|
|
53
53
|
GTL.synchronize { app(:rack, HIJACK_APP) { listen "#{host}:#{port}" } }
|
|
54
54
|
logger(Logger.new(err.path))
|
|
55
55
|
end
|
|
56
|
-
|
|
57
|
-
pid = fork do
|
|
58
|
-
ENV["YAHNS_FD"] = @srv.fileno.to_s
|
|
59
|
-
srv.start.join
|
|
60
|
-
end
|
|
56
|
+
pid = mkserver(cfg)
|
|
61
57
|
res = Net::HTTP.start(host, port) { |h| h.get("/hijack_req") }
|
|
62
58
|
assert_equal "request.hijacked", res.body
|
|
63
59
|
assert_equal 200, res.code.to_i
|