puma 4.3.12 → 5.6.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +1526 -524
- data/LICENSE +23 -20
- data/README.md +120 -36
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +63 -26
- data/docs/compile_options.md +21 -0
- data/docs/deployment.md +60 -69
- data/docs/fork_worker.md +33 -0
- 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/jungle/README.md +9 -0
- data/{tools → docs}/jungle/rc.d/README.md +1 -1
- data/{tools → docs}/jungle/rc.d/puma +2 -2
- data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +66 -0
- data/docs/nginx.md +1 -1
- data/docs/plugins.md +15 -15
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +46 -23
- data/docs/signals.md +13 -11
- data/docs/stats.md +142 -0
- data/docs/systemd.md +85 -128
- data/ext/puma_http11/PumaHttp11Service.java +2 -4
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +44 -10
- data/ext/puma_http11/http11_parser.c +45 -47
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +1 -1
- data/ext/puma_http11/http11_parser.rl +1 -1
- data/ext/puma_http11/http11_parser_common.rl +0 -0
- data/ext/puma_http11/mini_ssl.c +225 -89
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +5 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +3 -5
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +109 -67
- data/ext/puma_http11/puma_http11.c +32 -51
- data/lib/puma/app/status.rb +50 -36
- data/lib/puma/binder.rb +225 -106
- data/lib/puma/cli.rb +24 -18
- data/lib/puma/client.rb +146 -84
- data/lib/puma/cluster/worker.rb +173 -0
- data/lib/puma/cluster/worker_handle.rb +94 -0
- data/lib/puma/cluster.rb +212 -220
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +58 -49
- data/lib/puma/const.rb +22 -7
- data/lib/puma/control_cli.rb +99 -76
- data/lib/puma/detect.rb +29 -2
- data/lib/puma/dsl.rb +368 -96
- data/lib/puma/error_logger.rb +104 -0
- data/lib/puma/events.rb +55 -34
- data/lib/puma/io_buffer.rb +9 -2
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher.rb +128 -46
- data/lib/puma/minissl/context_builder.rb +14 -9
- data/lib/puma/minissl.rb +137 -50
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin/tmp_restart.rb +0 -0
- data/lib/puma/plugin.rb +3 -12
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +1 -5
- data/lib/puma/rack/urlmap.rb +0 -0
- data/lib/puma/rack_default.rb +0 -0
- data/lib/puma/reactor.rb +85 -369
- data/lib/puma/request.rb +489 -0
- data/lib/puma/runner.rb +46 -61
- data/lib/puma/server.rb +292 -763
- data/lib/puma/single.rb +9 -65
- data/lib/puma/state_file.rb +48 -8
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +125 -57
- data/lib/puma/util.rb +32 -4
- data/lib/puma.rb +48 -0
- data/lib/rack/handler/puma.rb +2 -3
- data/lib/rack/version_restriction.rb +15 -0
- data/tools/{docker/Dockerfile → Dockerfile} +1 -1
- data/tools/trickletest.rb +0 -0
- metadata +29 -24
- data/docs/tcp_mode.md +0 -96
- data/ext/puma_http11/io_buffer.c +0 -155
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
- data/lib/puma/accept_nonblock.rb +0 -29
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
- data/tools/jungle/upstart/README.md +0 -61
- data/tools/jungle/upstart/puma-manager.conf +0 -31
- data/tools/jungle/upstart/puma.conf +0 -69
data/lib/puma/minissl.rb
CHANGED
@@ -5,8 +5,18 @@ begin
|
|
5
5
|
rescue LoadError
|
6
6
|
end
|
7
7
|
|
8
|
+
# need for Puma::MiniSSL::OPENSSL constants used in `HAS_TLS1_3`
|
9
|
+
require 'puma/puma_http11'
|
10
|
+
|
8
11
|
module Puma
|
9
12
|
module MiniSSL
|
13
|
+
# Define constant at runtime, as it's easy to determine at built time,
|
14
|
+
# but Puma could (it shouldn't) be loaded with an older OpenSSL version
|
15
|
+
# @version 5.0.0
|
16
|
+
HAS_TLS1_3 = !IS_JRUBY &&
|
17
|
+
(OPENSSL_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) != -1 &&
|
18
|
+
(OPENSSL_LIBRARY_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) !=-1
|
19
|
+
|
10
20
|
class Socket
|
11
21
|
def initialize(socket, engine)
|
12
22
|
@socket = socket
|
@@ -14,6 +24,7 @@ module Puma
|
|
14
24
|
@peercert = nil
|
15
25
|
end
|
16
26
|
|
27
|
+
# @!attribute [r] to_io
|
17
28
|
def to_io
|
18
29
|
@socket
|
19
30
|
end
|
@@ -22,6 +33,27 @@ module Puma
|
|
22
33
|
@socket.closed?
|
23
34
|
end
|
24
35
|
|
36
|
+
# Returns a two element array,
|
37
|
+
# first is protocol version (SSL_get_version),
|
38
|
+
# second is 'handshake' state (SSL_state_string)
|
39
|
+
#
|
40
|
+
# Used for dropping tcp connections to ssl.
|
41
|
+
# See OpenSSL ssl/ssl_stat.c SSL_state_string for info
|
42
|
+
# @!attribute [r] ssl_version_state
|
43
|
+
# @version 5.0.0
|
44
|
+
#
|
45
|
+
def ssl_version_state
|
46
|
+
IS_JRUBY ? [nil, nil] : @engine.ssl_vers_st
|
47
|
+
end
|
48
|
+
|
49
|
+
# Used to check the handshake status, in particular when a TCP connection
|
50
|
+
# is made with TLSv1.3 as an available protocol
|
51
|
+
# @version 5.0.0
|
52
|
+
def bad_tlsv1_3?
|
53
|
+
HAS_TLS1_3 && @engine.ssl_vers_st == ['TLSv1.3', 'SSLERR']
|
54
|
+
end
|
55
|
+
private :bad_tlsv1_3?
|
56
|
+
|
25
57
|
def readpartial(size)
|
26
58
|
while true
|
27
59
|
output = @engine.read
|
@@ -67,6 +99,7 @@ module Puma
|
|
67
99
|
# ourselves.
|
68
100
|
raise IO::EAGAINWaitReadable
|
69
101
|
elsif data.nil?
|
102
|
+
raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
|
70
103
|
return nil
|
71
104
|
end
|
72
105
|
|
@@ -84,22 +117,23 @@ module Puma
|
|
84
117
|
def write(data)
|
85
118
|
return 0 if data.empty?
|
86
119
|
|
87
|
-
|
120
|
+
data_size = data.bytesize
|
121
|
+
need = data_size
|
88
122
|
|
89
123
|
while true
|
90
124
|
wrote = @engine.write data
|
91
|
-
enc = @engine.extract
|
92
125
|
|
93
|
-
|
94
|
-
|
95
|
-
|
126
|
+
enc_wr = ''.dup
|
127
|
+
while (enc = @engine.extract)
|
128
|
+
enc_wr << enc
|
96
129
|
end
|
130
|
+
@socket.write enc_wr unless enc_wr.empty?
|
97
131
|
|
98
132
|
need -= wrote
|
99
133
|
|
100
|
-
return
|
134
|
+
return data_size if need == 0
|
101
135
|
|
102
|
-
data = data
|
136
|
+
data = data.byteslice(wrote..-1)
|
103
137
|
end
|
104
138
|
end
|
105
139
|
|
@@ -107,14 +141,18 @@ module Puma
|
|
107
141
|
alias_method :<<, :write
|
108
142
|
|
109
143
|
# This is a temporary fix to deal with websockets code using
|
110
|
-
# write_nonblock.
|
144
|
+
# write_nonblock.
|
145
|
+
|
146
|
+
# The problem with implementing it properly
|
111
147
|
# is that it means we'd have to have the ability to rewind
|
112
148
|
# an engine because after we write+extract, the socket
|
113
149
|
# write_nonblock call might raise an exception and later
|
114
150
|
# code would pass the same data in, but the engine would think
|
115
|
-
# it had already written the data in.
|
116
|
-
#
|
117
|
-
#
|
151
|
+
# it had already written the data in.
|
152
|
+
#
|
153
|
+
# So for the time being (and since write blocking is quite rare),
|
154
|
+
# go ahead and actually block in write_nonblock.
|
155
|
+
#
|
118
156
|
def write_nonblock(data, *_)
|
119
157
|
write data
|
120
158
|
end
|
@@ -123,39 +161,27 @@ module Puma
|
|
123
161
|
@socket.flush
|
124
162
|
end
|
125
163
|
|
126
|
-
def read_and_drop(timeout = 1)
|
127
|
-
return :timeout unless IO.select([@socket], nil, nil, timeout)
|
128
|
-
return :eof unless read_nonblock(1024)
|
129
|
-
:drop
|
130
|
-
rescue Errno::EAGAIN
|
131
|
-
# do nothing
|
132
|
-
:eagain
|
133
|
-
end
|
134
|
-
|
135
|
-
def should_drop_bytes?
|
136
|
-
@engine.init? || !@engine.shutdown
|
137
|
-
end
|
138
|
-
|
139
164
|
def close
|
140
165
|
begin
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
return if [:timeout, :eof].include?(read_and_drop(1))
|
166
|
+
unless @engine.shutdown
|
167
|
+
while alert_data = @engine.extract
|
168
|
+
@socket.write alert_data
|
169
|
+
end
|
146
170
|
end
|
147
171
|
rescue IOError, SystemCallError
|
148
|
-
|
172
|
+
Puma::Util.purge_interrupt_queue
|
149
173
|
# nothing
|
150
174
|
ensure
|
151
175
|
@socket.close
|
152
176
|
end
|
153
177
|
end
|
154
178
|
|
179
|
+
# @!attribute [r] peeraddr
|
155
180
|
def peeraddr
|
156
181
|
@socket.peeraddr
|
157
182
|
end
|
158
183
|
|
184
|
+
# @!attribute [r] peercert
|
159
185
|
def peercert
|
160
186
|
return @peercert if @peercert
|
161
187
|
|
@@ -166,12 +192,13 @@ module Puma
|
|
166
192
|
end
|
167
193
|
end
|
168
194
|
|
169
|
-
if
|
195
|
+
if IS_JRUBY
|
196
|
+
OPENSSL_NO_SSL3 = false
|
197
|
+
OPENSSL_NO_TLS1 = false
|
198
|
+
|
170
199
|
class SSLError < StandardError
|
171
200
|
# Define this for jruby even though it isn't used.
|
172
201
|
end
|
173
|
-
|
174
|
-
def self.check; end
|
175
202
|
end
|
176
203
|
|
177
204
|
class Context
|
@@ -181,16 +208,25 @@ module Puma
|
|
181
208
|
def initialize
|
182
209
|
@no_tlsv1 = false
|
183
210
|
@no_tlsv1_1 = false
|
211
|
+
@key = nil
|
212
|
+
@cert = nil
|
213
|
+
@key_pem = nil
|
214
|
+
@cert_pem = nil
|
184
215
|
end
|
185
216
|
|
186
|
-
|
217
|
+
def check_file(file, desc)
|
218
|
+
raise ArgumentError, "#{desc} file '#{file}' does not exist" unless File.exist? file
|
219
|
+
raise ArgumentError, "#{desc} file '#{file}' is not readable" unless File.readable? file
|
220
|
+
end
|
221
|
+
|
222
|
+
if IS_JRUBY
|
187
223
|
# jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
|
188
224
|
attr_reader :keystore
|
189
225
|
attr_accessor :keystore_pass
|
190
226
|
attr_accessor :ssl_cipher_list
|
191
227
|
|
192
228
|
def keystore=(keystore)
|
193
|
-
|
229
|
+
check_file keystore, 'Keystore'
|
194
230
|
@keystore = keystore
|
195
231
|
end
|
196
232
|
|
@@ -203,38 +239,53 @@ module Puma
|
|
203
239
|
attr_reader :key
|
204
240
|
attr_reader :cert
|
205
241
|
attr_reader :ca
|
242
|
+
attr_reader :cert_pem
|
243
|
+
attr_reader :key_pem
|
206
244
|
attr_accessor :ssl_cipher_filter
|
245
|
+
attr_accessor :verification_flags
|
207
246
|
|
208
247
|
def key=(key)
|
209
|
-
|
248
|
+
check_file key, 'Key'
|
210
249
|
@key = key
|
211
250
|
end
|
212
251
|
|
213
252
|
def cert=(cert)
|
214
|
-
|
253
|
+
check_file cert, 'Cert'
|
215
254
|
@cert = cert
|
216
255
|
end
|
217
256
|
|
218
257
|
def ca=(ca)
|
219
|
-
|
258
|
+
check_file ca, 'ca'
|
220
259
|
@ca = ca
|
221
260
|
end
|
222
261
|
|
262
|
+
def cert_pem=(cert_pem)
|
263
|
+
raise ArgumentError, "'cert_pem' is not a String" unless cert_pem.is_a? String
|
264
|
+
@cert_pem = cert_pem
|
265
|
+
end
|
266
|
+
|
267
|
+
def key_pem=(key_pem)
|
268
|
+
raise ArgumentError, "'key_pem' is not a String" unless key_pem.is_a? String
|
269
|
+
@key_pem = key_pem
|
270
|
+
end
|
271
|
+
|
223
272
|
def check
|
224
|
-
raise "Key not configured"
|
225
|
-
raise "Cert not configured"
|
273
|
+
raise "Key not configured" if @key.nil? && @key_pem.nil?
|
274
|
+
raise "Cert not configured" if @cert.nil? && @cert_pem.nil?
|
226
275
|
end
|
227
276
|
end
|
228
277
|
|
229
278
|
# disables TLSv1
|
279
|
+
# @!attribute [w] no_tlsv1=
|
230
280
|
def no_tlsv1=(tlsv1)
|
231
|
-
raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1)
|
281
|
+
raise ArgumentError, "Invalid value of no_tlsv1=" unless ['true', 'false', true, false].include?(tlsv1)
|
232
282
|
@no_tlsv1 = tlsv1
|
233
283
|
end
|
234
284
|
|
235
285
|
# disables TLSv1 and TLSv1.1. Overrides `#no_tlsv1=`
|
286
|
+
# @!attribute [w] no_tlsv1_1=
|
236
287
|
def no_tlsv1_1=(tlsv1_1)
|
237
|
-
raise ArgumentError, "Invalid value of
|
288
|
+
raise ArgumentError, "Invalid value of no_tlsv1_1=" unless ['true', 'false', true, false].include?(tlsv1_1)
|
238
289
|
@no_tlsv1_1 = tlsv1_1
|
239
290
|
end
|
240
291
|
|
@@ -244,35 +295,71 @@ module Puma
|
|
244
295
|
VERIFY_PEER = 1
|
245
296
|
VERIFY_FAIL_IF_NO_PEER_CERT = 2
|
246
297
|
|
298
|
+
# https://github.com/openssl/openssl/blob/master/include/openssl/x509_vfy.h.in
|
299
|
+
# /* Certificate verify flags */
|
300
|
+
VERIFICATION_FLAGS = {
|
301
|
+
"USE_CHECK_TIME" => 0x2,
|
302
|
+
"CRL_CHECK" => 0x4,
|
303
|
+
"CRL_CHECK_ALL" => 0x8,
|
304
|
+
"IGNORE_CRITICAL" => 0x10,
|
305
|
+
"X509_STRICT" => 0x20,
|
306
|
+
"ALLOW_PROXY_CERTS" => 0x40,
|
307
|
+
"POLICY_CHECK" => 0x80,
|
308
|
+
"EXPLICIT_POLICY" => 0x100,
|
309
|
+
"INHIBIT_ANY" => 0x200,
|
310
|
+
"INHIBIT_MAP" => 0x400,
|
311
|
+
"NOTIFY_POLICY" => 0x800,
|
312
|
+
"EXTENDED_CRL_SUPPORT" => 0x1000,
|
313
|
+
"USE_DELTAS" => 0x2000,
|
314
|
+
"CHECK_SS_SIGNATURE" => 0x4000,
|
315
|
+
"TRUSTED_FIRST" => 0x8000,
|
316
|
+
"SUITEB_128_LOS_ONLY" => 0x10000,
|
317
|
+
"SUITEB_192_LOS" => 0x20000,
|
318
|
+
"SUITEB_128_LOS" => 0x30000,
|
319
|
+
"PARTIAL_CHAIN" => 0x80000,
|
320
|
+
"NO_ALT_CHAINS" => 0x100000,
|
321
|
+
"NO_CHECK_TIME" => 0x200000
|
322
|
+
}.freeze
|
323
|
+
|
247
324
|
class Server
|
248
325
|
def initialize(socket, ctx)
|
249
326
|
@socket = socket
|
250
327
|
@ctx = ctx
|
251
|
-
|
252
|
-
|
253
|
-
def to_io
|
254
|
-
@socket
|
328
|
+
@eng_ctx = IS_JRUBY ? @ctx : SSLContext.new(ctx)
|
255
329
|
end
|
256
330
|
|
257
331
|
def accept
|
258
332
|
@ctx.check
|
259
333
|
io = @socket.accept
|
260
|
-
engine = Engine.server @
|
261
|
-
|
334
|
+
engine = Engine.server @eng_ctx
|
262
335
|
Socket.new io, engine
|
263
336
|
end
|
264
337
|
|
265
338
|
def accept_nonblock
|
266
339
|
@ctx.check
|
267
340
|
io = @socket.accept_nonblock
|
268
|
-
engine = Engine.server @
|
269
|
-
|
341
|
+
engine = Engine.server @eng_ctx
|
270
342
|
Socket.new io, engine
|
271
343
|
end
|
272
344
|
|
345
|
+
# @!attribute [r] to_io
|
346
|
+
def to_io
|
347
|
+
@socket
|
348
|
+
end
|
349
|
+
|
350
|
+
# @!attribute [r] addr
|
351
|
+
# @version 5.0.0
|
352
|
+
def addr
|
353
|
+
@socket.addr
|
354
|
+
end
|
355
|
+
|
273
356
|
def close
|
274
357
|
@socket.close unless @socket.closed? # closed? call is for Windows
|
275
358
|
end
|
359
|
+
|
360
|
+
def closed?
|
361
|
+
@socket.closed?
|
362
|
+
end
|
276
363
|
end
|
277
364
|
end
|
278
365
|
end
|
data/lib/puma/null_io.rb
CHANGED
@@ -9,13 +9,17 @@ module Puma
|
|
9
9
|
nil
|
10
10
|
end
|
11
11
|
|
12
|
+
def string
|
13
|
+
""
|
14
|
+
end
|
15
|
+
|
12
16
|
def each
|
13
17
|
end
|
14
18
|
|
15
19
|
# Mimics IO#read with no data.
|
16
20
|
#
|
17
21
|
def read(count = nil, _buffer = nil)
|
18
|
-
|
22
|
+
count && count > 0 ? nil : ""
|
19
23
|
end
|
20
24
|
|
21
25
|
def rewind
|
@@ -32,6 +36,10 @@ module Puma
|
|
32
36
|
true
|
33
37
|
end
|
34
38
|
|
39
|
+
def sync
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
35
43
|
def sync=(v)
|
36
44
|
end
|
37
45
|
|
@@ -40,5 +48,14 @@ module Puma
|
|
40
48
|
|
41
49
|
def write(*ary)
|
42
50
|
end
|
51
|
+
|
52
|
+
def flush
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
# This is used as singleton class, so can't have state.
|
57
|
+
def closed?
|
58
|
+
false
|
59
|
+
end
|
43
60
|
end
|
44
61
|
end
|
File without changes
|
data/lib/puma/plugin.rb
CHANGED
@@ -10,7 +10,7 @@ module Puma
|
|
10
10
|
|
11
11
|
def create(name)
|
12
12
|
if cls = Plugins.find(name)
|
13
|
-
plugin = cls.new
|
13
|
+
plugin = cls.new
|
14
14
|
@instances << plugin
|
15
15
|
return plugin
|
16
16
|
end
|
@@ -64,7 +64,7 @@ module Puma
|
|
64
64
|
def fire_background
|
65
65
|
@background.each_with_index do |b, i|
|
66
66
|
Thread.new do
|
67
|
-
Puma.set_thread_name "
|
67
|
+
Puma.set_thread_name "plgn bg #{i}"
|
68
68
|
b.call
|
69
69
|
end
|
70
70
|
end
|
@@ -91,7 +91,7 @@ module Puma
|
|
91
91
|
path = ary.first[CALLER_FILE]
|
92
92
|
|
93
93
|
m = %r!puma/plugin/([^/]*)\.rb$!.match(path)
|
94
|
-
|
94
|
+
m[1]
|
95
95
|
end
|
96
96
|
|
97
97
|
def self.create(&blk)
|
@@ -104,17 +104,8 @@ module Puma
|
|
104
104
|
Plugins.register name, cls
|
105
105
|
end
|
106
106
|
|
107
|
-
def initialize(loader)
|
108
|
-
@loader = loader
|
109
|
-
end
|
110
|
-
|
111
107
|
def in_background(&blk)
|
112
108
|
Plugins.add_background blk
|
113
109
|
end
|
114
|
-
|
115
|
-
def workers_supported?
|
116
|
-
return false if Puma.jruby? || Puma.windows?
|
117
|
-
true
|
118
|
-
end
|
119
110
|
end
|
120
111
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class ClosedQueueError < StandardError; end
|
2
|
+
module Puma
|
3
|
+
|
4
|
+
# Queue#close was added in Ruby 2.3.
|
5
|
+
# Add a simple implementation for earlier Ruby versions.
|
6
|
+
#
|
7
|
+
module QueueClose
|
8
|
+
def close
|
9
|
+
num_waiting.times {push nil}
|
10
|
+
@closed = true
|
11
|
+
end
|
12
|
+
def closed?
|
13
|
+
@closed ||= false
|
14
|
+
end
|
15
|
+
def push(object)
|
16
|
+
raise ClosedQueueError if closed?
|
17
|
+
super
|
18
|
+
end
|
19
|
+
alias << push
|
20
|
+
def pop(non_block=false)
|
21
|
+
return nil if !non_block && closed? && empty?
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
::Queue.prepend QueueClose
|
26
|
+
end
|
data/lib/puma/rack/builder.rb
CHANGED
@@ -67,10 +67,6 @@ module Puma::Rack
|
|
67
67
|
options[:environment] = e
|
68
68
|
}
|
69
69
|
|
70
|
-
opts.on("-D", "--daemonize", "run daemonized in the background") { |d|
|
71
|
-
options[:daemonize] = d ? true : false
|
72
|
-
}
|
73
|
-
|
74
70
|
opts.on("-P", "--pid FILE", "file to store PID") { |f|
|
75
71
|
options[:pid] = ::File.expand_path(f)
|
76
72
|
}
|
@@ -169,7 +165,7 @@ module Puma::Rack
|
|
169
165
|
require config
|
170
166
|
app = Object.const_get(::File.basename(config, '.rb').capitalize)
|
171
167
|
end
|
172
|
-
|
168
|
+
[app, options]
|
173
169
|
end
|
174
170
|
|
175
171
|
def self.new_from_string(builder_script, file="(rackup)")
|
data/lib/puma/rack/urlmap.rb
CHANGED
File without changes
|
data/lib/puma/rack_default.rb
CHANGED
File without changes
|