puma 2.11.1 → 2.11.2
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 +4 -4
- data/History.txt +23 -0
- data/Manifest.txt +1 -0
- data/lib/puma/cli.rb +269 -303
- data/lib/puma/cluster.rb +1 -0
- data/lib/puma/configuration.rb +62 -328
- data/lib/puma/const.rb +1 -1
- data/lib/puma/dsl.rb +280 -0
- data/lib/puma/server.rb +24 -7
- data/puma.gemspec +1 -1
- metadata +4 -39
- data/test/test_app_status.rb +0 -92
- data/test/test_cli.rb +0 -173
- data/test/test_config.rb +0 -26
- data/test/test_http10.rb +0 -27
- data/test/test_http11.rb +0 -144
- data/test/test_integration.rb +0 -206
- data/test/test_iobuffer.rb +0 -38
- data/test/test_minissl.rb +0 -29
- data/test/test_null_io.rb +0 -31
- data/test/test_persistent.rb +0 -238
- data/test/test_puma_server.rb +0 -288
- data/test/test_puma_server_ssl.rb +0 -137
- 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 -182
- data/test/test_unix_socket.rb +0 -39
- data/test/test_ws.rb +0 -89
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,29 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'puma'
|
3
|
-
require 'puma/minissl'
|
4
|
-
|
5
|
-
class TestMiniSSL < Test::Unit::TestCase
|
6
|
-
|
7
|
-
if defined?(JRUBY_VERSION)
|
8
|
-
def test_raises_with_invalid_keystore_file
|
9
|
-
ctx = Puma::MiniSSL::Context.new
|
10
|
-
|
11
|
-
exception = assert_raise(ArgumentError) { ctx.keystore = "/no/such/keystore" }
|
12
|
-
assert_equal("No such keystore file '/no/such/keystore'", exception.message)
|
13
|
-
end
|
14
|
-
else
|
15
|
-
def test_raises_with_invalid_key_file
|
16
|
-
ctx = Puma::MiniSSL::Context.new
|
17
|
-
|
18
|
-
exception = assert_raise(ArgumentError) { ctx.key = "/no/such/key" }
|
19
|
-
assert_equal("No such key file '/no/such/key'", exception.message)
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_raises_with_invalid_cert_file
|
23
|
-
ctx = Puma::MiniSSL::Context.new
|
24
|
-
|
25
|
-
exception = assert_raise(ArgumentError) { ctx.cert = "/no/such/cert" }
|
26
|
-
assert_equal("No such cert file '/no/such/cert'", exception.message)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
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
|
data/test/test_puma_server.rb
DELETED
@@ -1,288 +0,0 @@
|
|
1
|
-
require "rbconfig"
|
2
|
-
require 'test/unit'
|
3
|
-
require 'socket'
|
4
|
-
require 'openssl'
|
5
|
-
|
6
|
-
require 'puma/minissl'
|
7
|
-
require 'puma/server'
|
8
|
-
|
9
|
-
require 'net/https'
|
10
|
-
|
11
|
-
class TestPumaServer < Test::Unit::TestCase
|
12
|
-
|
13
|
-
def setup
|
14
|
-
@port = 3212
|
15
|
-
@host = "127.0.0.1"
|
16
|
-
|
17
|
-
@app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
|
18
|
-
|
19
|
-
@events = Puma::Events.new STDOUT, STDERR
|
20
|
-
@server = Puma::Server.new @app, @events
|
21
|
-
end
|
22
|
-
|
23
|
-
def teardown
|
24
|
-
@server.stop(true)
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_proper_stringio_body
|
28
|
-
data = nil
|
29
|
-
|
30
|
-
@server.app = proc do |env|
|
31
|
-
data = env['rack.input'].read
|
32
|
-
[200, {}, ["ok"]]
|
33
|
-
end
|
34
|
-
|
35
|
-
@server.add_tcp_listener @host, @port
|
36
|
-
@server.run
|
37
|
-
|
38
|
-
fifteen = "1" * 15
|
39
|
-
|
40
|
-
sock = TCPSocket.new @host, @port
|
41
|
-
sock << "PUT / HTTP/1.0\r\nContent-Length: 30\r\n\r\n#{fifteen}"
|
42
|
-
sleep 0.1 # important so that the previous data is sent as a packet
|
43
|
-
sock << fifteen
|
44
|
-
|
45
|
-
sock.read
|
46
|
-
|
47
|
-
assert_equal "#{fifteen}#{fifteen}", data
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_puma_socket
|
51
|
-
body = "HTTP/1.1 750 Upgraded to Awesome\r\nDone: Yep!\r\n"
|
52
|
-
@server.app = proc do |env|
|
53
|
-
io = env['puma.socket']
|
54
|
-
|
55
|
-
io.write body
|
56
|
-
|
57
|
-
io.close
|
58
|
-
|
59
|
-
[-1, {}, []]
|
60
|
-
end
|
61
|
-
|
62
|
-
@server.add_tcp_listener @host, @port
|
63
|
-
@server.run
|
64
|
-
|
65
|
-
sock = TCPSocket.new @host, @port
|
66
|
-
sock << "PUT / HTTP/1.0\r\n\r\nHello"
|
67
|
-
|
68
|
-
assert_equal body, sock.read
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_very_large_return
|
72
|
-
giant = "x" * 2056610
|
73
|
-
|
74
|
-
@server.app = proc do |env|
|
75
|
-
[200, {}, [giant]]
|
76
|
-
end
|
77
|
-
|
78
|
-
@server.add_tcp_listener @host, @port
|
79
|
-
@server.run
|
80
|
-
|
81
|
-
sock = TCPSocket.new @host, @port
|
82
|
-
sock << "GET / HTTP/1.0\r\n\r\n"
|
83
|
-
|
84
|
-
while true
|
85
|
-
line = sock.gets
|
86
|
-
break if line == "\r\n"
|
87
|
-
end
|
88
|
-
|
89
|
-
out = sock.read
|
90
|
-
|
91
|
-
assert_equal giant.bytesize, out.bytesize
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_respect_x_forwarded_proto
|
95
|
-
@server.app = proc do |env|
|
96
|
-
[200, {}, [env['SERVER_PORT']]]
|
97
|
-
end
|
98
|
-
|
99
|
-
@server.add_tcp_listener @host, @port
|
100
|
-
@server.run
|
101
|
-
|
102
|
-
req = Net::HTTP::Get.new("/")
|
103
|
-
req['HOST'] = "example.com"
|
104
|
-
req['X_FORWARDED_PROTO'] = "https"
|
105
|
-
|
106
|
-
res = Net::HTTP.start @host, @port do |http|
|
107
|
-
http.request(req)
|
108
|
-
end
|
109
|
-
|
110
|
-
assert_equal "443", res.body
|
111
|
-
end
|
112
|
-
|
113
|
-
def test_default_server_port
|
114
|
-
@server.app = proc do |env|
|
115
|
-
[200, {}, [env['SERVER_PORT']]]
|
116
|
-
end
|
117
|
-
|
118
|
-
@server.add_tcp_listener @host, @port
|
119
|
-
@server.run
|
120
|
-
|
121
|
-
req = Net::HTTP::Get.new("/")
|
122
|
-
req['HOST'] = "example.com"
|
123
|
-
|
124
|
-
res = Net::HTTP.start @host, @port do |http|
|
125
|
-
http.request(req)
|
126
|
-
end
|
127
|
-
|
128
|
-
assert_equal "80", res.body
|
129
|
-
end
|
130
|
-
|
131
|
-
def test_HEAD_has_no_body
|
132
|
-
@server.app = proc { |env| [200, {"Foo" => "Bar"}, ["hello"]] }
|
133
|
-
|
134
|
-
@server.add_tcp_listener @host, @port
|
135
|
-
@server.run
|
136
|
-
|
137
|
-
sock = TCPSocket.new @host, @port
|
138
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
139
|
-
|
140
|
-
data = sock.read
|
141
|
-
|
142
|
-
assert_equal "HTTP/1.0 200 OK\r\nFoo: Bar\r\nContent-Length: 5\r\n\r\n", data
|
143
|
-
end
|
144
|
-
|
145
|
-
def test_GET_with_empty_body_has_sane_chunking
|
146
|
-
@server.app = proc { |env| [200, {}, [""]] }
|
147
|
-
|
148
|
-
@server.add_tcp_listener @host, @port
|
149
|
-
@server.run
|
150
|
-
|
151
|
-
sock = TCPSocket.new @host, @port
|
152
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
153
|
-
|
154
|
-
data = sock.read
|
155
|
-
|
156
|
-
assert_equal "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n", data
|
157
|
-
end
|
158
|
-
|
159
|
-
def test_GET_with_no_body_has_sane_chunking
|
160
|
-
@server.app = proc { |env| [200, {}, []] }
|
161
|
-
|
162
|
-
@server.add_tcp_listener @host, @port
|
163
|
-
@server.run
|
164
|
-
|
165
|
-
sock = TCPSocket.new @host, @port
|
166
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
167
|
-
|
168
|
-
data = sock.read
|
169
|
-
|
170
|
-
assert_equal "HTTP/1.0 200 OK\r\n\r\n", data
|
171
|
-
end
|
172
|
-
|
173
|
-
def test_doesnt_print_backtrace_in_production
|
174
|
-
@events = Puma::Events.strings
|
175
|
-
@server = Puma::Server.new @app, @events
|
176
|
-
|
177
|
-
@server.app = proc { |e| raise "don't leak me bro" }
|
178
|
-
@server.leak_stack_on_error = false
|
179
|
-
@server.add_tcp_listener @host, @port
|
180
|
-
@server.run
|
181
|
-
|
182
|
-
sock = TCPSocket.new @host, @port
|
183
|
-
sock << "GET / HTTP/1.0\r\n\r\n"
|
184
|
-
|
185
|
-
data = sock.read
|
186
|
-
|
187
|
-
assert_not_match(/don't leak me bro/, data)
|
188
|
-
assert_match(/HTTP\/1.0 500 Internal Server Error/, data)
|
189
|
-
end
|
190
|
-
|
191
|
-
def test_prints_custom_error
|
192
|
-
@events = Puma::Events.strings
|
193
|
-
re = lambda { |err| [302, {'Content-Type' => 'text', 'Location' => 'foo.html'}, ['302 found']] }
|
194
|
-
@server = Puma::Server.new @app, @events, {lowlevel_error_handler: re}
|
195
|
-
|
196
|
-
@server.app = proc { |e| raise "don't leak me bro" }
|
197
|
-
@server.add_tcp_listener @host, @port
|
198
|
-
@server.run
|
199
|
-
|
200
|
-
sock = TCPSocket.new @host, @port
|
201
|
-
sock << "GET / HTTP/1.0\r\n\r\n"
|
202
|
-
|
203
|
-
data = sock.read
|
204
|
-
assert_match(/HTTP\/1.0 302 Found/, data)
|
205
|
-
end
|
206
|
-
|
207
|
-
def test_custom_http_codes_10
|
208
|
-
@server.app = proc { |env| [449, {}, [""]] }
|
209
|
-
|
210
|
-
@server.add_tcp_listener @host, @port
|
211
|
-
@server.run
|
212
|
-
|
213
|
-
sock = TCPSocket.new @host, @port
|
214
|
-
|
215
|
-
sock << "GET / HTTP/1.0\r\n\r\n"
|
216
|
-
|
217
|
-
data = sock.read
|
218
|
-
|
219
|
-
assert_equal "HTTP/1.0 449 CUSTOM\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
220
|
-
end
|
221
|
-
|
222
|
-
def test_custom_http_codes_11
|
223
|
-
@server.app = proc { |env| [449, {}, [""]] }
|
224
|
-
|
225
|
-
@server.add_tcp_listener @host, @port
|
226
|
-
@server.run
|
227
|
-
|
228
|
-
sock = TCPSocket.new @host, @port
|
229
|
-
sock << "GET / HTTP/1.1\r\n\r\n"
|
230
|
-
|
231
|
-
data = sock.read
|
232
|
-
|
233
|
-
assert_equal "HTTP/1.1 449 CUSTOM\r\nContent-Length: 0\r\n\r\n", data
|
234
|
-
end
|
235
|
-
|
236
|
-
def test_HEAD_returns_content_headers
|
237
|
-
@server.app = proc { |env| [200, {"Content-Type" => "application/pdf",
|
238
|
-
"Content-Length" => "4242"}, []] }
|
239
|
-
|
240
|
-
@server.add_tcp_listener @host, @port
|
241
|
-
@server.run
|
242
|
-
|
243
|
-
sock = TCPSocket.new @host, @port
|
244
|
-
|
245
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
246
|
-
|
247
|
-
data = sock.read
|
248
|
-
|
249
|
-
assert_equal "HTTP/1.0 200 OK\r\nContent-Type: application/pdf\r\nContent-Length: 4242\r\n\r\n", data
|
250
|
-
end
|
251
|
-
|
252
|
-
def test_status_hook_fires_when_server_changes_states
|
253
|
-
|
254
|
-
states = []
|
255
|
-
|
256
|
-
@events.register(:state) { |s| states << s }
|
257
|
-
|
258
|
-
@server.app = proc { |env| [200, {}, [""]] }
|
259
|
-
|
260
|
-
@server.add_tcp_listener @host, @port
|
261
|
-
@server.run
|
262
|
-
|
263
|
-
sock = TCPSocket.new @host, @port
|
264
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
265
|
-
|
266
|
-
sock.read
|
267
|
-
|
268
|
-
assert_equal [:booting, :running], states
|
269
|
-
|
270
|
-
@server.stop(true)
|
271
|
-
|
272
|
-
assert_equal [:booting, :running, :stop, :done], states
|
273
|
-
end
|
274
|
-
|
275
|
-
def test_timeout_in_data_phase
|
276
|
-
@server.first_data_timeout = 2
|
277
|
-
@server.add_tcp_listener @host, @port
|
278
|
-
@server.run
|
279
|
-
|
280
|
-
client = TCPSocket.new @host, @port
|
281
|
-
|
282
|
-
client << "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\n"
|
283
|
-
|
284
|
-
data = client.gets
|
285
|
-
|
286
|
-
assert_equal "HTTP/1.1 408 Request Timeout\r\n", data
|
287
|
-
end
|
288
|
-
end
|