puma 2.16.0 → 3.11.4
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 +5 -5
- data/{History.txt → History.md} +489 -70
- data/README.md +143 -174
- data/docs/architecture.md +36 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +1 -1
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/nginx.md +2 -2
- data/docs/plugins.md +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +272 -0
- data/ext/puma_http11/extconf.rb +2 -0
- data/ext/puma_http11/http11_parser.c +291 -447
- data/ext/puma_http11/http11_parser.h +1 -0
- data/ext/puma_http11/http11_parser.java.rl +5 -5
- data/ext/puma_http11/http11_parser.rl +10 -9
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/io_buffer.c +8 -8
- data/ext/puma_http11/mini_ssl.c +64 -6
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +113 -131
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +9 -2
- data/ext/puma_http11/puma_http11.c +1 -0
- data/lib/puma/app/status.rb +9 -1
- data/lib/puma/binder.rb +90 -38
- data/lib/puma/cli.rb +134 -491
- data/lib/puma/client.rb +142 -4
- data/lib/puma/cluster.rb +132 -76
- data/lib/puma/commonlogger.rb +19 -20
- data/lib/puma/compat.rb +3 -7
- data/lib/puma/configuration.rb +206 -67
- data/lib/puma/const.rb +21 -31
- data/lib/puma/control_cli.rb +92 -103
- data/lib/puma/convenient.rb +23 -0
- data/lib/puma/daemon_ext.rb +6 -0
- data/lib/puma/detect.rb +10 -1
- data/lib/puma/dsl.rb +203 -45
- data/lib/puma/events.rb +22 -13
- data/lib/puma/io_buffer.rb +1 -1
- data/lib/puma/jruby_restart.rb +1 -2
- data/lib/puma/launcher.rb +431 -0
- data/lib/puma/minissl.rb +83 -4
- data/lib/puma/null_io.rb +19 -11
- data/lib/puma/plugin/tmp_restart.rb +34 -0
- data/lib/puma/plugin.rb +115 -0
- data/lib/puma/rack/backports/uri/common_193.rb +17 -13
- data/lib/puma/rack/builder.rb +3 -0
- data/lib/puma/rack/urlmap.rb +9 -8
- data/lib/puma/reactor.rb +18 -0
- data/lib/puma/runner.rb +43 -15
- data/lib/puma/server.rb +141 -35
- data/lib/puma/single.rb +16 -6
- data/lib/puma/state_file.rb +29 -0
- data/lib/puma/tcp_logger.rb +8 -1
- data/lib/puma/thread_pool.rb +60 -10
- data/lib/puma/util.rb +1 -5
- data/lib/puma.rb +13 -4
- data/lib/rack/handler/puma.rb +76 -29
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +9 -2
- data/tools/jungle/init.d/puma +86 -59
- data/tools/jungle/init.d/run-puma +16 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/jungle/upstart/puma.conf +1 -1
- data/tools/trickletest.rb +1 -1
- metadata +28 -95
- data/COPYING +0 -55
- data/Gemfile +0 -13
- data/Manifest.txt +0 -74
- data/Rakefile +0 -158
- data/docs/config.md +0 -0
- data/lib/puma/capistrano.rb +0 -94
- data/lib/puma/rack/backports/uri/common_18.rb +0 -56
- data/lib/puma/rack/backports/uri/common_192.rb +0 -52
- data/puma.gemspec +0 -52
data/lib/puma/binder.rb
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'socket'
|
|
3
|
+
|
|
1
4
|
require 'puma/const'
|
|
5
|
+
require 'puma/util'
|
|
2
6
|
|
|
3
7
|
module Puma
|
|
4
8
|
class Binder
|
|
@@ -10,6 +14,7 @@ module Puma
|
|
|
10
14
|
@events = events
|
|
11
15
|
@listeners = []
|
|
12
16
|
@inherited_fds = {}
|
|
17
|
+
@activated_sockets = {}
|
|
13
18
|
@unix_paths = []
|
|
14
19
|
|
|
15
20
|
@proto_env = {
|
|
@@ -21,13 +26,13 @@ module Puma
|
|
|
21
26
|
"SCRIPT_NAME".freeze => ENV['SCRIPT_NAME'] || "",
|
|
22
27
|
|
|
23
28
|
# I'd like to set a default CONTENT_TYPE here but some things
|
|
24
|
-
# depend on their not being a default set and
|
|
29
|
+
# depend on their not being a default set and inferring
|
|
25
30
|
# it from the content. And so if i set it here, it won't
|
|
26
31
|
# infer properly.
|
|
27
32
|
|
|
28
33
|
"QUERY_STRING".freeze => "",
|
|
29
34
|
SERVER_PROTOCOL => HTTP_11,
|
|
30
|
-
SERVER_SOFTWARE =>
|
|
35
|
+
SERVER_SOFTWARE => PUMA_SERVER_STRING,
|
|
31
36
|
GATEWAY_INTERFACE => CGI_VER
|
|
32
37
|
}
|
|
33
38
|
|
|
@@ -54,24 +59,23 @@ module Puma
|
|
|
54
59
|
fd, url = v.split(":", 2)
|
|
55
60
|
@inherited_fds[url] = fd.to_i
|
|
56
61
|
remove << k
|
|
57
|
-
|
|
58
|
-
if k =~ /LISTEN_FDS/ && ENV['LISTEN_PID'].to_i == $$
|
|
62
|
+
elsif k == 'LISTEN_FDS' && ENV['LISTEN_PID'].to_i == $$
|
|
59
63
|
v.to_i.times do |num|
|
|
60
64
|
fd = num + 3
|
|
61
65
|
sock = TCPServer.for_fd(fd)
|
|
62
66
|
begin
|
|
63
|
-
|
|
67
|
+
key = [ :unix, Socket.unpack_sockaddr_un(sock.getsockname) ]
|
|
64
68
|
rescue ArgumentError
|
|
65
69
|
port, addr = Socket.unpack_sockaddr_in(sock.getsockname)
|
|
66
70
|
if addr =~ /\:/
|
|
67
71
|
addr = "[#{addr}]"
|
|
68
72
|
end
|
|
69
|
-
|
|
73
|
+
key = [ :tcp, addr, port ]
|
|
70
74
|
end
|
|
71
|
-
@
|
|
75
|
+
@activated_sockets[key] = sock
|
|
76
|
+
@events.debug "Registered #{key.join ':'} for activation from LISTEN_FDS"
|
|
72
77
|
end
|
|
73
|
-
|
|
74
|
-
ENV.delete 'LISTEN_PID'
|
|
78
|
+
remove << k << 'LISTEN_PID'
|
|
75
79
|
end
|
|
76
80
|
end
|
|
77
81
|
|
|
@@ -88,6 +92,9 @@ module Puma
|
|
|
88
92
|
if fd = @inherited_fds.delete(str)
|
|
89
93
|
logger.log "* Inherited #{str}"
|
|
90
94
|
io = inherit_tcp_listener uri.host, uri.port, fd
|
|
95
|
+
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
|
|
96
|
+
logger.log "* Activated #{str}"
|
|
97
|
+
io = inherit_tcp_listener uri.host, uri.port, sock
|
|
91
98
|
else
|
|
92
99
|
params = Util.parse_query uri.query
|
|
93
100
|
|
|
@@ -98,18 +105,22 @@ module Puma
|
|
|
98
105
|
io = add_tcp_listener uri.host, uri.port, opt, bak
|
|
99
106
|
end
|
|
100
107
|
|
|
101
|
-
@listeners << [str, io]
|
|
108
|
+
@listeners << [str, io] if io
|
|
102
109
|
when "unix"
|
|
103
110
|
path = "#{uri.host}#{uri.path}".gsub("%20", " ")
|
|
104
111
|
|
|
105
112
|
if fd = @inherited_fds.delete(str)
|
|
106
113
|
logger.log "* Inherited #{str}"
|
|
107
114
|
io = inherit_unix_listener path, fd
|
|
115
|
+
elsif sock = @activated_sockets.delete([ :unix, path ])
|
|
116
|
+
logger.log "* Activated #{str}"
|
|
117
|
+
io = inherit_unix_listener path, sock
|
|
108
118
|
else
|
|
109
119
|
logger.log "* Listening on #{str}"
|
|
110
120
|
|
|
111
121
|
umask = nil
|
|
112
122
|
mode = nil
|
|
123
|
+
backlog = 1024
|
|
113
124
|
|
|
114
125
|
if uri.query
|
|
115
126
|
params = Util.parse_query uri.query
|
|
@@ -121,18 +132,22 @@ module Puma
|
|
|
121
132
|
if u = params['mode']
|
|
122
133
|
mode = Integer('0'+u)
|
|
123
134
|
end
|
|
135
|
+
|
|
136
|
+
if u = params['backlog']
|
|
137
|
+
backlog = Integer(u)
|
|
138
|
+
end
|
|
124
139
|
end
|
|
125
140
|
|
|
126
|
-
io = add_unix_listener path, umask, mode
|
|
141
|
+
io = add_unix_listener path, umask, mode, backlog
|
|
127
142
|
end
|
|
128
143
|
|
|
129
144
|
@listeners << [str, io]
|
|
130
145
|
when "ssl"
|
|
131
|
-
MiniSSL.check
|
|
132
|
-
|
|
133
146
|
params = Util.parse_query uri.query
|
|
134
147
|
require 'puma/minissl'
|
|
135
148
|
|
|
149
|
+
MiniSSL.check
|
|
150
|
+
|
|
136
151
|
ctx = MiniSSL::Context.new
|
|
137
152
|
|
|
138
153
|
if defined?(JRUBY_VERSION)
|
|
@@ -165,33 +180,36 @@ module Puma
|
|
|
165
180
|
@events.error "Please specify the SSL ca via 'ca='"
|
|
166
181
|
end
|
|
167
182
|
end
|
|
168
|
-
|
|
183
|
+
|
|
169
184
|
ctx.ca = params['ca'] if params['ca']
|
|
185
|
+
end
|
|
170
186
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
end
|
|
187
|
+
if params['verify_mode']
|
|
188
|
+
ctx.verify_mode = case params['verify_mode']
|
|
189
|
+
when "peer"
|
|
190
|
+
MiniSSL::VERIFY_PEER
|
|
191
|
+
when "force_peer"
|
|
192
|
+
MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
|
193
|
+
when "none"
|
|
194
|
+
MiniSSL::VERIFY_NONE
|
|
195
|
+
else
|
|
196
|
+
@events.error "Please specify a valid verify_mode="
|
|
197
|
+
MiniSSL::VERIFY_NONE
|
|
198
|
+
end
|
|
184
199
|
end
|
|
185
200
|
|
|
186
201
|
if fd = @inherited_fds.delete(str)
|
|
187
202
|
logger.log "* Inherited #{str}"
|
|
188
|
-
io =
|
|
203
|
+
io = inherit_ssl_listener fd, ctx
|
|
204
|
+
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
|
|
205
|
+
logger.log "* Activated #{str}"
|
|
206
|
+
io = inherit_ssl_listener sock, ctx
|
|
189
207
|
else
|
|
190
208
|
logger.log "* Listening on #{str}"
|
|
191
209
|
io = add_ssl_listener uri.host, uri.port, ctx
|
|
192
210
|
end
|
|
193
211
|
|
|
194
|
-
@listeners << [str, io]
|
|
212
|
+
@listeners << [str, io] if io
|
|
195
213
|
else
|
|
196
214
|
logger.error "Invalid URI: #{str}"
|
|
197
215
|
end
|
|
@@ -203,12 +221,7 @@ module Puma
|
|
|
203
221
|
logger.log "* Closing unused inherited connection: #{str}"
|
|
204
222
|
|
|
205
223
|
begin
|
|
206
|
-
|
|
207
|
-
fd.close
|
|
208
|
-
else
|
|
209
|
-
IO.for_fd(fd).close
|
|
210
|
-
end
|
|
211
|
-
|
|
224
|
+
IO.for_fd(fd).close
|
|
212
225
|
rescue SystemCallError
|
|
213
226
|
end
|
|
214
227
|
|
|
@@ -220,6 +233,22 @@ module Puma
|
|
|
220
233
|
end
|
|
221
234
|
end
|
|
222
235
|
|
|
236
|
+
# Also close any unused activated sockets
|
|
237
|
+
@activated_sockets.each do |key, sock|
|
|
238
|
+
logger.log "* Closing unused activated socket: #{key.join ':'}"
|
|
239
|
+
begin
|
|
240
|
+
sock.close
|
|
241
|
+
rescue SystemCallError
|
|
242
|
+
end
|
|
243
|
+
# We have to unlink a unix socket path that's not being used
|
|
244
|
+
File.unlink key[1] if key[0] == :unix
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def loopback_addresses
|
|
249
|
+
Socket.ip_address_list.select do |addrinfo|
|
|
250
|
+
addrinfo.ipv6_loopback? || addrinfo.ipv4_loopback?
|
|
251
|
+
end.map { |addrinfo| addrinfo.ip_address }.uniq
|
|
223
252
|
end
|
|
224
253
|
|
|
225
254
|
# Tell the server to listen on host +host+, port +port+.
|
|
@@ -230,6 +259,13 @@ module Puma
|
|
|
230
259
|
# allow to accumulate before returning connection refused.
|
|
231
260
|
#
|
|
232
261
|
def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
|
|
262
|
+
if host == "localhost"
|
|
263
|
+
loopback_addresses.each do |addr|
|
|
264
|
+
add_tcp_listener addr, port, optimize_for_latency, backlog
|
|
265
|
+
end
|
|
266
|
+
return
|
|
267
|
+
end
|
|
268
|
+
|
|
233
269
|
host = host[1..-2] if host and host[0..0] == '['
|
|
234
270
|
s = TCPServer.new(host, port)
|
|
235
271
|
if optimize_for_latency
|
|
@@ -237,10 +273,14 @@ module Puma
|
|
|
237
273
|
end
|
|
238
274
|
s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
|
239
275
|
s.listen backlog
|
|
276
|
+
@connected_port = s.addr[1]
|
|
277
|
+
|
|
240
278
|
@ios << s
|
|
241
279
|
s
|
|
242
280
|
end
|
|
243
281
|
|
|
282
|
+
attr_reader :connected_port
|
|
283
|
+
|
|
244
284
|
def inherit_tcp_listener(host, port, fd)
|
|
245
285
|
if fd.kind_of? TCPServer
|
|
246
286
|
s = fd
|
|
@@ -258,6 +298,13 @@ module Puma
|
|
|
258
298
|
|
|
259
299
|
MiniSSL.check
|
|
260
300
|
|
|
301
|
+
if host == "localhost"
|
|
302
|
+
loopback_addresses.each do |addr|
|
|
303
|
+
add_ssl_listener addr, port, ctx, optimize_for_latency, backlog
|
|
304
|
+
end
|
|
305
|
+
return
|
|
306
|
+
end
|
|
307
|
+
|
|
261
308
|
host = host[1..-2] if host[0..0] == '['
|
|
262
309
|
s = TCPServer.new(host, port)
|
|
263
310
|
if optimize_for_latency
|
|
@@ -275,11 +322,15 @@ module Puma
|
|
|
275
322
|
s
|
|
276
323
|
end
|
|
277
324
|
|
|
278
|
-
def
|
|
325
|
+
def inherit_ssl_listener(fd, ctx)
|
|
279
326
|
require 'puma/minissl'
|
|
280
327
|
MiniSSL.check
|
|
281
328
|
|
|
282
|
-
|
|
329
|
+
if fd.kind_of? TCPServer
|
|
330
|
+
s = fd
|
|
331
|
+
else
|
|
332
|
+
s = TCPServer.for_fd(fd)
|
|
333
|
+
end
|
|
283
334
|
ssl = MiniSSL::Server.new(s, ctx)
|
|
284
335
|
|
|
285
336
|
env = @proto_env.dup
|
|
@@ -293,7 +344,7 @@ module Puma
|
|
|
293
344
|
|
|
294
345
|
# Tell the server to listen on +path+ as a UNIX domain socket.
|
|
295
346
|
#
|
|
296
|
-
def add_unix_listener(path, umask=nil, mode=nil)
|
|
347
|
+
def add_unix_listener(path, umask=nil, mode=nil, backlog=1024)
|
|
297
348
|
@unix_paths << path
|
|
298
349
|
|
|
299
350
|
# Let anyone connect by default
|
|
@@ -314,6 +365,7 @@ module Puma
|
|
|
314
365
|
end
|
|
315
366
|
|
|
316
367
|
s = UNIXServer.new(path)
|
|
368
|
+
s.listen backlog
|
|
317
369
|
@ios << s
|
|
318
370
|
ensure
|
|
319
371
|
File.umask old_mask
|