puma 2.7.0 → 3.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +5 -13
- data/DEPLOYMENT.md +91 -0
- data/Gemfile +3 -2
- data/History.txt +624 -1
- data/Manifest.txt +15 -3
- data/README.md +129 -14
- data/Rakefile +3 -3
- data/bin/puma-wild +31 -0
- data/bin/pumactl +1 -1
- data/docs/nginx.md +1 -1
- data/docs/signals.md +43 -0
- data/ext/puma_http11/extconf.rb +7 -2
- data/ext/puma_http11/http11_parser.java.rl +5 -5
- data/ext/puma_http11/io_buffer.c +1 -1
- data/ext/puma_http11/mini_ssl.c +233 -18
- data/ext/puma_http11/org/jruby/puma/Http11.java +12 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +39 -39
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +245 -195
- data/ext/puma_http11/puma_http11.c +12 -4
- data/lib/puma.rb +1 -0
- data/lib/puma/app/status.rb +7 -0
- data/lib/puma/binder.rb +108 -39
- data/lib/puma/capistrano.rb +23 -6
- data/lib/puma/cli.rb +141 -446
- data/lib/puma/client.rb +48 -1
- data/lib/puma/cluster.rb +207 -58
- data/lib/puma/commonlogger.rb +107 -0
- data/lib/puma/configuration.rb +262 -235
- data/lib/puma/const.rb +97 -14
- data/lib/puma/control_cli.rb +85 -77
- data/lib/puma/convenient.rb +23 -0
- data/lib/puma/daemon_ext.rb +11 -4
- data/lib/puma/detect.rb +8 -1
- data/lib/puma/dsl.rb +456 -0
- data/lib/puma/events.rb +35 -18
- data/lib/puma/jruby_restart.rb +1 -1
- data/lib/puma/launcher.rb +399 -0
- data/lib/puma/minissl.rb +49 -20
- data/lib/puma/null_io.rb +15 -0
- data/lib/puma/plugin.rb +104 -0
- data/lib/puma/plugin/tmp_restart.rb +35 -0
- data/lib/puma/rack/backports/uri/common_18.rb +56 -0
- data/lib/puma/rack/backports/uri/common_192.rb +52 -0
- data/lib/puma/rack/backports/uri/common_193.rb +29 -0
- data/lib/puma/rack/builder.rb +295 -0
- data/lib/puma/rack/urlmap.rb +90 -0
- data/lib/puma/reactor.rb +14 -1
- data/lib/puma/runner.rb +35 -17
- data/lib/puma/server.rb +161 -58
- data/lib/puma/single.rb +15 -10
- data/lib/puma/state_file.rb +29 -0
- data/lib/puma/thread_pool.rb +88 -13
- data/lib/puma/util.rb +123 -0
- data/lib/rack/handler/puma.rb +35 -29
- data/puma.gemspec +2 -4
- data/tools/jungle/init.d/README.md +2 -2
- data/tools/jungle/init.d/puma +69 -7
- data/tools/jungle/upstart/puma.conf +8 -2
- metadata +51 -71
- data/COPYING +0 -55
- data/TODO +0 -5
- data/lib/puma/rack_patch.rb +0 -45
- data/test/test_app_status.rb +0 -92
- data/test/test_cli.rb +0 -173
- data/test/test_config.rb +0 -16
- data/test/test_http10.rb +0 -27
- data/test/test_http11.rb +0 -145
- data/test/test_integration.rb +0 -165
- data/test/test_iobuffer.rb +0 -38
- data/test/test_minissl.rb +0 -25
- data/test/test_null_io.rb +0 -31
- data/test/test_persistent.rb +0 -238
- data/test/test_puma_server.rb +0 -292
- data/test/test_rack_handler.rb +0 -10
- data/test/test_rack_server.rb +0 -141
- data/test/test_tcp_rack.rb +0 -42
- data/test/test_thread_pool.rb +0 -156
- data/test/test_unix_socket.rb +0 -39
- data/test/test_ws.rb +0 -89
data/test/test_integration.rb
DELETED
@@ -1,165 +0,0 @@
|
|
1
|
-
require "rbconfig"
|
2
|
-
require 'test/unit'
|
3
|
-
require 'socket'
|
4
|
-
require 'timeout'
|
5
|
-
require 'net/http'
|
6
|
-
require 'tempfile'
|
7
|
-
|
8
|
-
require 'puma/cli'
|
9
|
-
require 'puma/control_cli'
|
10
|
-
|
11
|
-
# These don't run on travis because they're too fragile
|
12
|
-
|
13
|
-
class TestIntegration < Test::Unit::TestCase
|
14
|
-
def setup
|
15
|
-
@state_path = "test/test_puma.state"
|
16
|
-
@bind_path = "test/test_server.sock"
|
17
|
-
@control_path = "test/test_control.sock"
|
18
|
-
@tcp_port = 9998
|
19
|
-
|
20
|
-
@server = nil
|
21
|
-
@script = nil
|
22
|
-
|
23
|
-
@wait, @ready = IO.pipe
|
24
|
-
|
25
|
-
@events = Puma::Events.strings
|
26
|
-
@events.on_booted { @ready << "!" }
|
27
|
-
end
|
28
|
-
|
29
|
-
def teardown
|
30
|
-
File.unlink @state_path rescue nil
|
31
|
-
File.unlink @bind_path rescue nil
|
32
|
-
File.unlink @control_path rescue nil
|
33
|
-
|
34
|
-
@wait.close
|
35
|
-
@ready.close
|
36
|
-
|
37
|
-
if @server
|
38
|
-
Process.kill "INT", @server.pid
|
39
|
-
begin
|
40
|
-
Process.wait @server.pid
|
41
|
-
rescue Errno::ECHILD
|
42
|
-
end
|
43
|
-
|
44
|
-
@server.close
|
45
|
-
end
|
46
|
-
|
47
|
-
if @script
|
48
|
-
@script.close!
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def server(opts)
|
53
|
-
core = "#{Gem.ruby} -rubygems -Ilib bin/puma"
|
54
|
-
cmd = "#{core} --restart-cmd '#{core}' -b tcp://127.0.0.1:#{@tcp_port} #{opts}"
|
55
|
-
tf = Tempfile.new "puma-test"
|
56
|
-
tf.puts "exec #{cmd}"
|
57
|
-
tf.close
|
58
|
-
|
59
|
-
@script = tf
|
60
|
-
|
61
|
-
@server = IO.popen("sh #{tf.path}", "r")
|
62
|
-
|
63
|
-
true while @server.gets =~ /Ctrl-C/
|
64
|
-
|
65
|
-
sleep 1
|
66
|
-
|
67
|
-
@server
|
68
|
-
end
|
69
|
-
|
70
|
-
def signal(which)
|
71
|
-
Process.kill which, @server.pid
|
72
|
-
end
|
73
|
-
|
74
|
-
def wait_booted
|
75
|
-
@wait.sysread 1
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_stop_via_pumactl
|
79
|
-
if defined?(JRUBY_VERSION) || RbConfig::CONFIG["host_os"] =~ /mingw|mswin/
|
80
|
-
assert true
|
81
|
-
return
|
82
|
-
end
|
83
|
-
|
84
|
-
cli = Puma::CLI.new %W!-q -S #{@state_path} -b unix://#{@bind_path} --control unix://#{@control_path} test/hello.ru!, @events
|
85
|
-
|
86
|
-
t = Thread.new do
|
87
|
-
cli.run
|
88
|
-
end
|
89
|
-
|
90
|
-
wait_booted
|
91
|
-
|
92
|
-
s = UNIXSocket.new @bind_path
|
93
|
-
s << "GET / HTTP/1.0\r\n\r\n"
|
94
|
-
assert_equal "Hello World", s.read.split("\r\n").last
|
95
|
-
|
96
|
-
sout = StringIO.new
|
97
|
-
|
98
|
-
ccli = Puma::ControlCLI.new %W!-S #{@state_path} stop!, sout
|
99
|
-
|
100
|
-
ccli.run
|
101
|
-
|
102
|
-
assert_kind_of Thread, t.join(1), "server didn't stop"
|
103
|
-
end
|
104
|
-
|
105
|
-
def notest_restart_closes_keepalive_sockets
|
106
|
-
server("-q test/hello.ru")
|
107
|
-
|
108
|
-
s = TCPSocket.new "localhost", @tcp_port
|
109
|
-
s << "GET / HTTP/1.1\r\n\r\n"
|
110
|
-
true until s.gets == "\r\n"
|
111
|
-
|
112
|
-
s.readpartial(20)
|
113
|
-
signal :USR2
|
114
|
-
|
115
|
-
true while @server.gets =~ /Ctrl-C/
|
116
|
-
sleep 1
|
117
|
-
|
118
|
-
s.write "GET / HTTP/1.1\r\n\r\n"
|
119
|
-
|
120
|
-
assert_raises Errno::ECONNRESET do
|
121
|
-
Timeout.timeout(2) do
|
122
|
-
raise Errno::ECONNRESET unless s.read(2)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
s = TCPSocket.new "localhost", @tcp_port
|
127
|
-
s << "GET / HTTP/1.0\r\n\r\n"
|
128
|
-
assert_equal "Hello World", s.read.split("\r\n").last
|
129
|
-
end
|
130
|
-
|
131
|
-
def notest_restart_closes_keepalive_sockets_workers
|
132
|
-
server("-q -w 2 test/hello.ru")
|
133
|
-
|
134
|
-
s = TCPSocket.new "localhost", @tcp_port
|
135
|
-
s << "GET / HTTP/1.1\r\n\r\n"
|
136
|
-
true until s.gets == "\r\n"
|
137
|
-
|
138
|
-
s.readpartial(20)
|
139
|
-
signal :USR2
|
140
|
-
|
141
|
-
true while @server.gets =~ /Ctrl-C/
|
142
|
-
sleep 1
|
143
|
-
|
144
|
-
s.write "GET / HTTP/1.1\r\n\r\n"
|
145
|
-
|
146
|
-
assert_raises Errno::ECONNRESET do
|
147
|
-
Timeout.timeout(2) do
|
148
|
-
raise Errno::ECONNRESET unless s.read(2)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
s = TCPSocket.new "localhost", @tcp_port
|
153
|
-
s << "GET / HTTP/1.0\r\n\r\n"
|
154
|
-
assert_equal "Hello World", s.read.split("\r\n").last
|
155
|
-
end
|
156
|
-
|
157
|
-
def test_bad_query_string_outputs_400
|
158
|
-
server "-q test/hello.ru 2>&1"
|
159
|
-
|
160
|
-
s = TCPSocket.new "localhost", @tcp_port
|
161
|
-
s << "GET /?h=% HTTP/1.0\r\n\r\n"
|
162
|
-
data = s.read
|
163
|
-
assert_equal "HTTP/1.1 400 Bad Request\r\n\r\n", data
|
164
|
-
end
|
165
|
-
end unless ENV['TRAVIS']
|
data/test/test_iobuffer.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'puma/io_buffer'
|
2
|
-
require 'test/unit'
|
3
|
-
|
4
|
-
class TestIOBuffer < Test::Unit::TestCase
|
5
|
-
attr_accessor :iobuf
|
6
|
-
def setup
|
7
|
-
self.iobuf = Puma::IOBuffer.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_initial_size
|
11
|
-
assert_equal 0, iobuf.used
|
12
|
-
assert iobuf.capacity > 0
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_append_op
|
16
|
-
iobuf << "abc"
|
17
|
-
assert_equal "abc", iobuf.to_s
|
18
|
-
iobuf << "123"
|
19
|
-
assert_equal "abc123", iobuf.to_s
|
20
|
-
assert_equal 6, iobuf.used
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_append
|
24
|
-
expected = "mary had a little lamb"
|
25
|
-
iobuf.append("mary", " ", "had ", "a little", " lamb")
|
26
|
-
assert_equal expected, iobuf.to_s
|
27
|
-
assert_equal expected.length, iobuf.used
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_reset
|
31
|
-
iobuf << "content"
|
32
|
-
assert_equal "content", iobuf.to_s
|
33
|
-
iobuf.reset
|
34
|
-
assert_equal 0, iobuf.used
|
35
|
-
assert_equal "", iobuf.to_s
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
data/test/test_minissl.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
|
3
|
-
unless defined? JRUBY_VERSION
|
4
|
-
|
5
|
-
require 'puma'
|
6
|
-
require 'puma/minissl'
|
7
|
-
|
8
|
-
class TestMiniSSL < Test::Unit::TestCase
|
9
|
-
|
10
|
-
def test_raises_with_invalid_key_file
|
11
|
-
ctx = Puma::MiniSSL::Context.new
|
12
|
-
|
13
|
-
exception = assert_raise(ArgumentError) { ctx.key = "/no/such/key" }
|
14
|
-
assert_equal("No such key file '/no/such/key'", exception.message)
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_raises_with_invalid_cert_file
|
18
|
-
ctx = Puma::MiniSSL::Context.new
|
19
|
-
|
20
|
-
exception = assert_raise(ArgumentError) { ctx.cert = "/no/such/cert" }
|
21
|
-
assert_equal("No such cert file '/no/such/cert'", exception.message)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
data/test/test_null_io.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'puma/null_io'
|
2
|
-
require 'test/unit'
|
3
|
-
|
4
|
-
class TestNullIO < Test::Unit::TestCase
|
5
|
-
attr_accessor :nio
|
6
|
-
def setup
|
7
|
-
self.nio = Puma::NullIO.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_read_with_no_arguments
|
11
|
-
assert_equal "", nio.read
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_read_with_nil_length
|
15
|
-
assert_equal "", nio.read(nil)
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_read_with_zero_length
|
19
|
-
assert_equal "", nio.read(0)
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_read_with_positive_integer_length
|
23
|
-
assert_nil nio.read(1)
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_read_with_length_and_buffer
|
27
|
-
buf = ""
|
28
|
-
assert_nil nio.read(1,buf)
|
29
|
-
assert_equal "", buf
|
30
|
-
end
|
31
|
-
end
|
data/test/test_persistent.rb
DELETED
@@ -1,238 +0,0 @@
|
|
1
|
-
require 'puma'
|
2
|
-
require 'test/unit'
|
3
|
-
require 'timeout'
|
4
|
-
|
5
|
-
class TestPersistent < Test::Unit::TestCase
|
6
|
-
def setup
|
7
|
-
@valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
|
8
|
-
@close_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n"
|
9
|
-
@http10_request = "GET / HTTP/1.0\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
|
10
|
-
@keep_request = "GET / HTTP/1.0\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: Keep-Alive\r\n\r\n"
|
11
|
-
|
12
|
-
@valid_post = "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nhello"
|
13
|
-
@valid_no_body = "GET / HTTP/1.1\r\nHost: test.com\r\nX-Status: 204\r\nContent-Type: text/plain\r\n\r\n"
|
14
|
-
|
15
|
-
@headers = { "X-Header" => "Works" }
|
16
|
-
@body = ["Hello"]
|
17
|
-
@inputs = []
|
18
|
-
|
19
|
-
@simple = lambda do |env|
|
20
|
-
@inputs << env['rack.input']
|
21
|
-
status = Integer(env['HTTP_X_STATUS'] || 200)
|
22
|
-
[status, @headers, @body]
|
23
|
-
end
|
24
|
-
|
25
|
-
@host = "127.0.0.1"
|
26
|
-
@port = 9988
|
27
|
-
|
28
|
-
@server = Puma::Server.new @simple
|
29
|
-
@server.add_tcp_listener "127.0.0.1", 9988
|
30
|
-
@server.max_threads = 1
|
31
|
-
@server.run
|
32
|
-
|
33
|
-
@client = TCPSocket.new "127.0.0.1", 9988
|
34
|
-
end
|
35
|
-
|
36
|
-
def teardown
|
37
|
-
@client.close
|
38
|
-
@server.stop(true)
|
39
|
-
end
|
40
|
-
|
41
|
-
def lines(count, s=@client)
|
42
|
-
str = ""
|
43
|
-
timeout(5) do
|
44
|
-
count.times { str << s.gets }
|
45
|
-
end
|
46
|
-
str
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_one_with_content_length
|
50
|
-
@client << @valid_request
|
51
|
-
sz = @body[0].size.to_s
|
52
|
-
|
53
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
54
|
-
assert_equal "Hello", @client.read(5)
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_two_back_to_back
|
58
|
-
@client << @valid_request
|
59
|
-
sz = @body[0].size.to_s
|
60
|
-
|
61
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
62
|
-
assert_equal "Hello", @client.read(5)
|
63
|
-
|
64
|
-
@client << @valid_request
|
65
|
-
sz = @body[0].size.to_s
|
66
|
-
|
67
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
68
|
-
assert_equal "Hello", @client.read(5)
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_post_then_get
|
72
|
-
@client << @valid_post
|
73
|
-
sz = @body[0].size.to_s
|
74
|
-
|
75
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
76
|
-
assert_equal "Hello", @client.read(5)
|
77
|
-
|
78
|
-
@client << @valid_request
|
79
|
-
sz = @body[0].size.to_s
|
80
|
-
|
81
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
82
|
-
assert_equal "Hello", @client.read(5)
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_no_body_then_get
|
86
|
-
@client << @valid_no_body
|
87
|
-
assert_equal "HTTP/1.1 204 No Content\r\nX-Header: Works\r\n\r\n", lines(3)
|
88
|
-
|
89
|
-
@client << @valid_request
|
90
|
-
sz = @body[0].size.to_s
|
91
|
-
|
92
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
93
|
-
assert_equal "Hello", @client.read(5)
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_chunked
|
97
|
-
@body << "Chunked"
|
98
|
-
|
99
|
-
@client << @valid_request
|
100
|
-
|
101
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n7\r\nChunked\r\n0\r\n\r\n", lines(10)
|
102
|
-
end
|
103
|
-
|
104
|
-
def test_no_chunked_in_http10
|
105
|
-
@body << "Chunked"
|
106
|
-
|
107
|
-
@client << @http10_request
|
108
|
-
|
109
|
-
assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: close\r\n\r\n", lines(4)
|
110
|
-
assert_equal "HelloChunked", @client.read
|
111
|
-
end
|
112
|
-
|
113
|
-
def test_hex
|
114
|
-
str = "This is longer and will be in hex"
|
115
|
-
@body << str
|
116
|
-
|
117
|
-
@client << @valid_request
|
118
|
-
|
119
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n#{str.size.to_s(16)}\r\n#{str}\r\n0\r\n\r\n", lines(10)
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
def test_client11_close
|
124
|
-
@client << @close_request
|
125
|
-
sz = @body[0].size.to_s
|
126
|
-
|
127
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nConnection: close\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
|
128
|
-
assert_equal "Hello", @client.read(5)
|
129
|
-
end
|
130
|
-
|
131
|
-
def test_client10_close
|
132
|
-
@client << @http10_request
|
133
|
-
sz = @body[0].size.to_s
|
134
|
-
|
135
|
-
assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: close\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
|
136
|
-
assert_equal "Hello", @client.read(5)
|
137
|
-
end
|
138
|
-
|
139
|
-
def test_one_with_keep_alive_header
|
140
|
-
@client << @keep_request
|
141
|
-
sz = @body[0].size.to_s
|
142
|
-
|
143
|
-
assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: Keep-Alive\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
|
144
|
-
assert_equal "Hello", @client.read(5)
|
145
|
-
end
|
146
|
-
|
147
|
-
def test_persistent_timeout
|
148
|
-
@server.persistent_timeout = 2
|
149
|
-
@client << @valid_request
|
150
|
-
sz = @body[0].size.to_s
|
151
|
-
|
152
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
153
|
-
assert_equal "Hello", @client.read(5)
|
154
|
-
|
155
|
-
sleep 3
|
156
|
-
|
157
|
-
assert_raises EOFError do
|
158
|
-
@client.read_nonblock(1)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def test_app_sets_content_length
|
163
|
-
@body = ["hello", " world"]
|
164
|
-
@headers['Content-Length'] = "11"
|
165
|
-
|
166
|
-
@client << @valid_request
|
167
|
-
|
168
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: 11\r\n\r\n",
|
169
|
-
lines(4)
|
170
|
-
assert_equal "hello world", @client.read(11)
|
171
|
-
end
|
172
|
-
|
173
|
-
def test_allow_app_to_chunk_itself
|
174
|
-
@headers = {'Transfer-Encoding' => "chunked" }
|
175
|
-
|
176
|
-
@body = ["5\r\nhello\r\n0\r\n\r\n"]
|
177
|
-
|
178
|
-
@client << @valid_request
|
179
|
-
|
180
|
-
assert_equal "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n0\r\n\r\n", lines(7)
|
181
|
-
end
|
182
|
-
|
183
|
-
|
184
|
-
def test_two_requests_in_one_chunk
|
185
|
-
@server.persistent_timeout = 3
|
186
|
-
|
187
|
-
req = @valid_request.to_s
|
188
|
-
req << "GET /second HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
|
189
|
-
|
190
|
-
@client << req
|
191
|
-
|
192
|
-
sz = @body[0].size.to_s
|
193
|
-
|
194
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
195
|
-
assert_equal "Hello", @client.read(5)
|
196
|
-
|
197
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
198
|
-
assert_equal "Hello", @client.read(5)
|
199
|
-
end
|
200
|
-
|
201
|
-
def test_second_request_not_in_first_req_body
|
202
|
-
@server.persistent_timeout = 3
|
203
|
-
|
204
|
-
req = @valid_request.to_s
|
205
|
-
req << "GET /second HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
|
206
|
-
|
207
|
-
@client << req
|
208
|
-
|
209
|
-
sz = @body[0].size.to_s
|
210
|
-
|
211
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
212
|
-
assert_equal "Hello", @client.read(5)
|
213
|
-
|
214
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
|
215
|
-
assert_equal "Hello", @client.read(5)
|
216
|
-
|
217
|
-
assert_kind_of Puma::NullIO, @inputs[0]
|
218
|
-
assert_kind_of Puma::NullIO, @inputs[1]
|
219
|
-
end
|
220
|
-
|
221
|
-
def test_keepalive_doesnt_starve_clients
|
222
|
-
sz = @body[0].size.to_s
|
223
|
-
|
224
|
-
@client << @valid_request
|
225
|
-
|
226
|
-
c2 = TCPSocket.new @host, @port
|
227
|
-
c2 << @valid_request
|
228
|
-
|
229
|
-
out = IO.select([c2], nil, nil, 1)
|
230
|
-
|
231
|
-
assert out, "select returned nil"
|
232
|
-
assert_equal c2, out.first.first
|
233
|
-
|
234
|
-
assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4, c2)
|
235
|
-
assert_equal "Hello", c2.read(5)
|
236
|
-
end
|
237
|
-
|
238
|
-
end
|