puma 2.7.0 → 3.1.1
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.
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_puma_server.rb
DELETED
@@ -1,292 +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
|
-
|
22
|
-
if defined?(JRUBY_VERSION)
|
23
|
-
@ssl_key = File.expand_path "../../examples/puma/keystore.jks", __FILE__
|
24
|
-
@ssl_cert = @ssl_key
|
25
|
-
else
|
26
|
-
@ssl_key = File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__
|
27
|
-
@ssl_cert = File.expand_path "../../examples/puma/cert_puma.pem", __FILE__
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def teardown
|
32
|
-
@server.stop(true)
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_url_scheme_for_https
|
36
|
-
ctx = Puma::MiniSSL::Context.new
|
37
|
-
|
38
|
-
ctx.key = @ssl_key
|
39
|
-
ctx.cert = @ssl_cert
|
40
|
-
|
41
|
-
ctx.verify_mode = Puma::MiniSSL::VERIFY_NONE
|
42
|
-
|
43
|
-
@server.add_ssl_listener @host, @port, ctx
|
44
|
-
@server.run
|
45
|
-
|
46
|
-
http = Net::HTTP.new @host, @port
|
47
|
-
http.use_ssl = true
|
48
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
49
|
-
|
50
|
-
body = nil
|
51
|
-
http.start do
|
52
|
-
req = Net::HTTP::Get.new "/", {}
|
53
|
-
|
54
|
-
http.request(req) do |rep|
|
55
|
-
body = rep.body
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
assert_equal "https", body
|
60
|
-
end unless defined? JRUBY_VERSION
|
61
|
-
|
62
|
-
def test_proper_stringio_body
|
63
|
-
data = nil
|
64
|
-
|
65
|
-
@server.app = proc do |env|
|
66
|
-
data = env['rack.input'].read
|
67
|
-
[200, {}, ["ok"]]
|
68
|
-
end
|
69
|
-
|
70
|
-
@server.add_tcp_listener @host, @port
|
71
|
-
@server.run
|
72
|
-
|
73
|
-
fifteen = "1" * 15
|
74
|
-
|
75
|
-
sock = TCPSocket.new @host, @port
|
76
|
-
sock << "PUT / HTTP/1.0\r\nContent-Length: 30\r\n\r\n#{fifteen}"
|
77
|
-
sleep 0.1 # important so that the previous data is sent as a packet
|
78
|
-
sock << fifteen
|
79
|
-
|
80
|
-
sock.read
|
81
|
-
|
82
|
-
assert_equal "#{fifteen}#{fifteen}", data
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_puma_socket
|
86
|
-
body = "HTTP/1.1 750 Upgraded to Awesome\r\nDone: Yep!\r\n"
|
87
|
-
@server.app = proc do |env|
|
88
|
-
io = env['puma.socket']
|
89
|
-
|
90
|
-
io.write body
|
91
|
-
|
92
|
-
io.close
|
93
|
-
|
94
|
-
[-1, {}, []]
|
95
|
-
end
|
96
|
-
|
97
|
-
@server.add_tcp_listener @host, @port
|
98
|
-
@server.run
|
99
|
-
|
100
|
-
sock = TCPSocket.new @host, @port
|
101
|
-
sock << "PUT / HTTP/1.0\r\n\r\nHello"
|
102
|
-
|
103
|
-
assert_equal body, sock.read
|
104
|
-
end
|
105
|
-
|
106
|
-
def test_very_large_return
|
107
|
-
giant = "x" * 2056610
|
108
|
-
|
109
|
-
@server.app = proc do |env|
|
110
|
-
[200, {}, [giant]]
|
111
|
-
end
|
112
|
-
|
113
|
-
@server.add_tcp_listener @host, @port
|
114
|
-
@server.run
|
115
|
-
|
116
|
-
sock = TCPSocket.new @host, @port
|
117
|
-
sock << "GET / HTTP/1.0\r\n\r\n"
|
118
|
-
|
119
|
-
while true
|
120
|
-
line = sock.gets
|
121
|
-
break if line == "\r\n"
|
122
|
-
end
|
123
|
-
|
124
|
-
out = sock.read
|
125
|
-
|
126
|
-
assert_equal giant.bytesize, out.bytesize
|
127
|
-
end
|
128
|
-
|
129
|
-
def test_respect_x_forwarded_proto
|
130
|
-
@server.app = proc do |env|
|
131
|
-
[200, {}, [env['SERVER_PORT']]]
|
132
|
-
end
|
133
|
-
|
134
|
-
@server.add_tcp_listener @host, @port
|
135
|
-
@server.run
|
136
|
-
|
137
|
-
req = Net::HTTP::Get.new("/")
|
138
|
-
req['HOST'] = "example.com"
|
139
|
-
req['X_FORWARDED_PROTO'] = "https"
|
140
|
-
|
141
|
-
res = Net::HTTP.start @host, @port do |http|
|
142
|
-
http.request(req)
|
143
|
-
end
|
144
|
-
|
145
|
-
assert_equal "443", res.body
|
146
|
-
end
|
147
|
-
|
148
|
-
def test_default_server_port
|
149
|
-
@server.app = proc do |env|
|
150
|
-
[200, {}, [env['SERVER_PORT']]]
|
151
|
-
end
|
152
|
-
|
153
|
-
@server.add_tcp_listener @host, @port
|
154
|
-
@server.run
|
155
|
-
|
156
|
-
req = Net::HTTP::Get.new("/")
|
157
|
-
req['HOST'] = "example.com"
|
158
|
-
|
159
|
-
res = Net::HTTP.start @host, @port do |http|
|
160
|
-
http.request(req)
|
161
|
-
end
|
162
|
-
|
163
|
-
assert_equal "80", res.body
|
164
|
-
end
|
165
|
-
|
166
|
-
def test_HEAD_has_no_body
|
167
|
-
@server.app = proc { |env| [200, {"Foo" => "Bar"}, ["hello"]] }
|
168
|
-
|
169
|
-
@server.add_tcp_listener @host, @port
|
170
|
-
@server.run
|
171
|
-
|
172
|
-
sock = TCPSocket.new @host, @port
|
173
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
174
|
-
|
175
|
-
data = sock.read
|
176
|
-
|
177
|
-
assert_equal "HTTP/1.0 200 OK\r\nFoo: Bar\r\nContent-Length: 5\r\n\r\n", data
|
178
|
-
end
|
179
|
-
|
180
|
-
def test_GET_with_empty_body_has_sane_chunking
|
181
|
-
@server.app = proc { |env| [200, {}, [""]] }
|
182
|
-
|
183
|
-
@server.add_tcp_listener @host, @port
|
184
|
-
@server.run
|
185
|
-
|
186
|
-
sock = TCPSocket.new @host, @port
|
187
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
188
|
-
|
189
|
-
data = sock.read
|
190
|
-
|
191
|
-
assert_equal "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n", data
|
192
|
-
end
|
193
|
-
|
194
|
-
def test_GET_with_no_body_has_sane_chunking
|
195
|
-
@server.app = proc { |env| [200, {}, []] }
|
196
|
-
|
197
|
-
@server.add_tcp_listener @host, @port
|
198
|
-
@server.run
|
199
|
-
|
200
|
-
sock = TCPSocket.new @host, @port
|
201
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
202
|
-
|
203
|
-
data = sock.read
|
204
|
-
|
205
|
-
assert_equal "HTTP/1.0 200 OK\r\n\r\n", data
|
206
|
-
end
|
207
|
-
|
208
|
-
def test_doesnt_print_backtrace_in_production
|
209
|
-
@events = Puma::Events.strings
|
210
|
-
@server = Puma::Server.new @app, @events
|
211
|
-
|
212
|
-
@server.app = proc { |e| raise "don't leak me bro" }
|
213
|
-
@server.leak_stack_on_error = false
|
214
|
-
@server.add_tcp_listener @host, @port
|
215
|
-
@server.run
|
216
|
-
|
217
|
-
sock = TCPSocket.new @host, @port
|
218
|
-
sock << "GET / HTTP/1.0\r\n\r\n"
|
219
|
-
|
220
|
-
data = sock.read
|
221
|
-
|
222
|
-
assert_not_match(/don't leak me bro/, data)
|
223
|
-
end
|
224
|
-
|
225
|
-
def test_custom_http_codes_10
|
226
|
-
@server.app = proc { |env| [449, {}, [""]] }
|
227
|
-
|
228
|
-
@server.add_tcp_listener @host, @port
|
229
|
-
@server.run
|
230
|
-
|
231
|
-
sock = TCPSocket.new @host, @port
|
232
|
-
|
233
|
-
sock << "GET / HTTP/1.0\r\n\r\n"
|
234
|
-
|
235
|
-
data = sock.read
|
236
|
-
|
237
|
-
assert_equal "HTTP/1.0 449 CUSTOM\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
238
|
-
end
|
239
|
-
|
240
|
-
def test_custom_http_codes_11
|
241
|
-
@server.app = proc { |env| [449, {}, [""]] }
|
242
|
-
|
243
|
-
@server.add_tcp_listener @host, @port
|
244
|
-
@server.run
|
245
|
-
|
246
|
-
sock = TCPSocket.new @host, @port
|
247
|
-
sock << "GET / HTTP/1.1\r\n\r\n"
|
248
|
-
|
249
|
-
data = sock.read
|
250
|
-
|
251
|
-
assert_equal "HTTP/1.1 449 CUSTOM\r\nContent-Length: 0\r\n\r\n", data
|
252
|
-
end
|
253
|
-
|
254
|
-
def test_HEAD_returns_content_headers
|
255
|
-
@server.app = proc { |env| [200, {"Content-Type" => "application/pdf",
|
256
|
-
"Content-Length" => "4242"}, []] }
|
257
|
-
|
258
|
-
@server.add_tcp_listener @host, @port
|
259
|
-
@server.run
|
260
|
-
|
261
|
-
sock = TCPSocket.new @host, @port
|
262
|
-
|
263
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
264
|
-
|
265
|
-
data = sock.read
|
266
|
-
|
267
|
-
assert_equal "HTTP/1.0 200 OK\r\nContent-Type: application/pdf\r\nContent-Length: 4242\r\n\r\n", data
|
268
|
-
end
|
269
|
-
|
270
|
-
def test_status_hook_fires_when_server_changes_states
|
271
|
-
|
272
|
-
states = []
|
273
|
-
|
274
|
-
@events.register(:state) { |s| states << s }
|
275
|
-
|
276
|
-
@server.app = proc { |env| [200, {}, [""]] }
|
277
|
-
|
278
|
-
@server.add_tcp_listener @host, @port
|
279
|
-
@server.run
|
280
|
-
|
281
|
-
sock = TCPSocket.new @host, @port
|
282
|
-
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
283
|
-
|
284
|
-
sock.read
|
285
|
-
|
286
|
-
assert_equal [:booting, :running], states
|
287
|
-
|
288
|
-
@server.stop(true)
|
289
|
-
|
290
|
-
assert_equal [:booting, :running, :stop, :done], states
|
291
|
-
end
|
292
|
-
end
|
data/test/test_rack_handler.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
|
3
|
-
class TestPumaUnixSocket < Test::Unit::TestCase
|
4
|
-
def test_handler
|
5
|
-
handler = Rack::Handler.get(:puma)
|
6
|
-
assert_equal Rack::Handler::Puma, handler
|
7
|
-
handler = Rack::Handler.get('Puma')
|
8
|
-
assert_equal Rack::Handler::Puma, handler
|
9
|
-
end
|
10
|
-
end
|
data/test/test_rack_server.rb
DELETED
@@ -1,141 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'puma'
|
3
|
-
require 'rack/lint'
|
4
|
-
require 'test/testhelp'
|
5
|
-
require 'rack/commonlogger'
|
6
|
-
require 'puma/rack_patch'
|
7
|
-
|
8
|
-
class TestRackServer < Test::Unit::TestCase
|
9
|
-
|
10
|
-
class ErrorChecker
|
11
|
-
def initialize(app)
|
12
|
-
@app = app
|
13
|
-
@exception = nil
|
14
|
-
@env = nil
|
15
|
-
end
|
16
|
-
|
17
|
-
attr_reader :exception, :env
|
18
|
-
|
19
|
-
def call(env)
|
20
|
-
begin
|
21
|
-
@env = env
|
22
|
-
return @app.call(env)
|
23
|
-
rescue Exception => e
|
24
|
-
@exception = e
|
25
|
-
|
26
|
-
[
|
27
|
-
500,
|
28
|
-
{ "X-Exception" => e.message, "X-Exception-Class" => e.class.to_s },
|
29
|
-
["Error detected"]
|
30
|
-
]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class ServerLint < Rack::Lint
|
36
|
-
def call(env)
|
37
|
-
assert("No env given") { env }
|
38
|
-
check_env env
|
39
|
-
|
40
|
-
@app.call(env)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def setup
|
45
|
-
@valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
|
46
|
-
|
47
|
-
@simple = lambda { |env| [200, { "X-Header" => "Works" }, ["Hello"]] }
|
48
|
-
@server = Puma::Server.new @simple
|
49
|
-
@server.add_tcp_listener "127.0.0.1", 9998
|
50
|
-
|
51
|
-
@stopped = false
|
52
|
-
end
|
53
|
-
|
54
|
-
def stop
|
55
|
-
@server.stop(true)
|
56
|
-
@stopped = true
|
57
|
-
end
|
58
|
-
|
59
|
-
def teardown
|
60
|
-
@server.stop(true) unless @stopped
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_lint
|
64
|
-
@checker = ErrorChecker.new ServerLint.new(@simple)
|
65
|
-
@server.app = @checker
|
66
|
-
|
67
|
-
@server.run
|
68
|
-
|
69
|
-
hit(['http://127.0.0.1:9998/test'])
|
70
|
-
|
71
|
-
stop
|
72
|
-
|
73
|
-
if exc = @checker.exception
|
74
|
-
raise exc
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_large_post_body
|
79
|
-
@checker = ErrorChecker.new ServerLint.new(@simple)
|
80
|
-
@server.app = @checker
|
81
|
-
|
82
|
-
@server.run
|
83
|
-
|
84
|
-
big = "x" * (1024 * 16)
|
85
|
-
|
86
|
-
Net::HTTP.post_form URI.parse('http://127.0.0.1:9998/test'),
|
87
|
-
{ "big" => big }
|
88
|
-
|
89
|
-
stop
|
90
|
-
|
91
|
-
if exc = @checker.exception
|
92
|
-
raise exc
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_path_info
|
97
|
-
input = nil
|
98
|
-
@server.app = lambda { |env| input = env; @simple.call(env) }
|
99
|
-
@server.run
|
100
|
-
|
101
|
-
hit(['http://127.0.0.1:9998/test/a/b/c'])
|
102
|
-
|
103
|
-
stop
|
104
|
-
|
105
|
-
assert_equal "/test/a/b/c", input['PATH_INFO']
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_after_reply
|
109
|
-
closed = false
|
110
|
-
|
111
|
-
@server.app = lambda do |env|
|
112
|
-
env['rack.after_reply'] << lambda { closed = true }
|
113
|
-
@simple.call(env)
|
114
|
-
end
|
115
|
-
|
116
|
-
@server.run
|
117
|
-
|
118
|
-
hit(['http://127.0.0.1:9998/test'])
|
119
|
-
|
120
|
-
stop
|
121
|
-
|
122
|
-
assert_equal true, closed
|
123
|
-
end
|
124
|
-
|
125
|
-
def test_common_logger
|
126
|
-
log = StringIO.new
|
127
|
-
|
128
|
-
logger = Rack::CommonLogger.new(@simple, log)
|
129
|
-
|
130
|
-
@server.app = logger
|
131
|
-
|
132
|
-
@server.run
|
133
|
-
|
134
|
-
hit(['http://127.0.0.1:9998/test'])
|
135
|
-
|
136
|
-
stop
|
137
|
-
|
138
|
-
assert_match %r!GET /test HTTP/1\.1!, log.string
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
data/test/test_tcp_rack.rb
DELETED
@@ -1,42 +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 TestTCPRack < Test::Unit::TestCase
|
12
|
-
|
13
|
-
def setup
|
14
|
-
@port = 3212
|
15
|
-
@host = "127.0.0.1"
|
16
|
-
|
17
|
-
@events = Puma::Events.new STDOUT, STDERR
|
18
|
-
@server = Puma::Server.new nil, @events
|
19
|
-
end
|
20
|
-
|
21
|
-
def teardown
|
22
|
-
@server.stop(true)
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_passes_the_socket
|
26
|
-
@server.tcp_mode!
|
27
|
-
|
28
|
-
body = "We sell hats for a discount!\n"
|
29
|
-
|
30
|
-
@server.app = proc do |env, socket|
|
31
|
-
socket << body
|
32
|
-
socket.close
|
33
|
-
end
|
34
|
-
|
35
|
-
@server.add_tcp_listener @host, @port
|
36
|
-
@server.run
|
37
|
-
|
38
|
-
sock = TCPSocket.new @host, @port
|
39
|
-
|
40
|
-
assert_equal body, sock.read
|
41
|
-
end
|
42
|
-
end
|