puma 5.6.8 → 6.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +332 -16
- data/README.md +79 -29
- data/bin/puma-wild +1 -1
- data/docs/compile_options.md +34 -0
- data/docs/fork_worker.md +1 -3
- data/docs/kubernetes.md +12 -0
- data/docs/nginx.md +1 -1
- data/docs/restart.md +1 -0
- data/docs/systemd.md +3 -6
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/extconf.rb +16 -9
- data/ext/puma_http11/http11_parser.c +1 -1
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +2 -2
- data/ext/puma_http11/http11_parser.rl +2 -2
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +127 -19
- data/ext/puma_http11/org/jruby/puma/Http11.java +5 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +157 -53
- data/ext/puma_http11/puma_http11.c +17 -9
- data/lib/puma/app/status.rb +4 -4
- data/lib/puma/binder.rb +50 -53
- data/lib/puma/cli.rb +16 -18
- data/lib/puma/client.rb +59 -19
- data/lib/puma/cluster/worker.rb +18 -11
- data/lib/puma/cluster/worker_handle.rb +4 -1
- data/lib/puma/cluster.rb +102 -40
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +77 -59
- data/lib/puma/const.rb +137 -92
- data/lib/puma/control_cli.rb +15 -11
- data/lib/puma/detect.rb +7 -4
- data/lib/puma/dsl.rb +250 -56
- data/lib/puma/error_logger.rb +18 -9
- data/lib/puma/events.rb +6 -126
- data/lib/puma/io_buffer.rb +39 -4
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +102 -175
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +26 -12
- data/lib/puma/minissl.rb +104 -11
- data/lib/puma/null_io.rb +16 -2
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/rack/builder.rb +6 -6
- data/lib/puma/rack/urlmap.rb +1 -1
- data/lib/puma/rack_default.rb +19 -4
- data/lib/puma/reactor.rb +19 -10
- data/lib/puma/request.rb +380 -172
- data/lib/puma/runner.rb +56 -20
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +137 -89
- data/lib/puma/single.rb +13 -11
- data/lib/puma/state_file.rb +3 -6
- data/lib/puma/thread_pool.rb +57 -19
- data/lib/puma/util.rb +0 -11
- data/lib/puma.rb +9 -10
- data/lib/rack/handler/puma.rb +113 -86
- data/tools/Dockerfile +2 -2
- metadata +11 -7
- data/lib/puma/queue_close.rb +0 -26
- data/lib/puma/systemd.rb +0 -46
- data/lib/rack/version_restriction.rb +0 -15
@@ -36,13 +36,13 @@ static VALUE global_request_method;
|
|
36
36
|
static VALUE global_request_uri;
|
37
37
|
static VALUE global_fragment;
|
38
38
|
static VALUE global_query_string;
|
39
|
-
static VALUE
|
39
|
+
static VALUE global_server_protocol;
|
40
40
|
static VALUE global_request_path;
|
41
41
|
|
42
42
|
/** Defines common length and error messages for input length validation. */
|
43
43
|
#define QUOTE(s) #s
|
44
|
-
#define
|
45
|
-
#define DEF_MAX_LENGTH(N,length) const size_t MAX_##N##_LENGTH = length; const char *MAX_##N##_LENGTH_ERR = "HTTP element " # N " is longer than the "
|
44
|
+
#define EXPAND_MAX_LENGTH_VALUE(s) QUOTE(s)
|
45
|
+
#define DEF_MAX_LENGTH(N,length) const size_t MAX_##N##_LENGTH = length; const char *MAX_##N##_LENGTH_ERR = "HTTP element " # N " is longer than the " EXPAND_MAX_LENGTH_VALUE(length) " allowed length (was %d)"
|
46
46
|
|
47
47
|
/** Validates the max length of given input and throws an HttpParserError exception if over. */
|
48
48
|
#define VALIDATE_MAX_LENGTH(len, N) if(len > MAX_##N##_LENGTH) { rb_raise(eHttpParserError, MAX_##N##_LENGTH_ERR, len); }
|
@@ -52,15 +52,23 @@ static VALUE global_request_path;
|
|
52
52
|
|
53
53
|
|
54
54
|
/* Defines the maximum allowed lengths for various input elements.*/
|
55
|
+
#ifndef PUMA_REQUEST_URI_MAX_LENGTH
|
56
|
+
#define PUMA_REQUEST_URI_MAX_LENGTH (1024 * 12)
|
57
|
+
#endif
|
58
|
+
|
59
|
+
#ifndef PUMA_REQUEST_PATH_MAX_LENGTH
|
60
|
+
#define PUMA_REQUEST_PATH_MAX_LENGTH (8192)
|
61
|
+
#endif
|
62
|
+
|
55
63
|
#ifndef PUMA_QUERY_STRING_MAX_LENGTH
|
56
64
|
#define PUMA_QUERY_STRING_MAX_LENGTH (1024 * 10)
|
57
65
|
#endif
|
58
66
|
|
59
67
|
DEF_MAX_LENGTH(FIELD_NAME, 256);
|
60
68
|
DEF_MAX_LENGTH(FIELD_VALUE, 80 * 1024);
|
61
|
-
DEF_MAX_LENGTH(REQUEST_URI,
|
69
|
+
DEF_MAX_LENGTH(REQUEST_URI, PUMA_REQUEST_URI_MAX_LENGTH);
|
62
70
|
DEF_MAX_LENGTH(FRAGMENT, 1024); /* Don't know if this length is specified somewhere or not */
|
63
|
-
DEF_MAX_LENGTH(REQUEST_PATH,
|
71
|
+
DEF_MAX_LENGTH(REQUEST_PATH, PUMA_REQUEST_PATH_MAX_LENGTH);
|
64
72
|
DEF_MAX_LENGTH(QUERY_STRING, PUMA_QUERY_STRING_MAX_LENGTH);
|
65
73
|
DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
|
66
74
|
|
@@ -236,10 +244,10 @@ void query_string(puma_parser* hp, const char *at, size_t length)
|
|
236
244
|
rb_hash_aset(hp->request, global_query_string, val);
|
237
245
|
}
|
238
246
|
|
239
|
-
void
|
247
|
+
void server_protocol(puma_parser* hp, const char *at, size_t length)
|
240
248
|
{
|
241
249
|
VALUE val = rb_str_new(at, length);
|
242
|
-
rb_hash_aset(hp->request,
|
250
|
+
rb_hash_aset(hp->request, global_server_protocol, val);
|
243
251
|
}
|
244
252
|
|
245
253
|
/** Finalizes the request header to have a bunch of stuff that's
|
@@ -281,7 +289,7 @@ VALUE HttpParser_alloc(VALUE klass)
|
|
281
289
|
hp->fragment = fragment;
|
282
290
|
hp->request_path = request_path;
|
283
291
|
hp->query_string = query_string;
|
284
|
-
hp->
|
292
|
+
hp->server_protocol = server_protocol;
|
285
293
|
hp->header_done = header_done;
|
286
294
|
hp->request = Qnil;
|
287
295
|
|
@@ -461,7 +469,7 @@ void Init_puma_http11(void)
|
|
461
469
|
DEF_GLOBAL(request_uri, "REQUEST_URI");
|
462
470
|
DEF_GLOBAL(fragment, "FRAGMENT");
|
463
471
|
DEF_GLOBAL(query_string, "QUERY_STRING");
|
464
|
-
DEF_GLOBAL(
|
472
|
+
DEF_GLOBAL(server_protocol, "SERVER_PROTOCOL");
|
465
473
|
DEF_GLOBAL(request_path, "REQUEST_PATH");
|
466
474
|
|
467
475
|
eHttpParserError = rb_define_class_under(mPuma, "HttpParserError", rb_eIOError);
|
data/lib/puma/app/status.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
require_relative '../json_serialization'
|
3
3
|
|
4
4
|
module Puma
|
5
5
|
module App
|
@@ -80,13 +80,13 @@ module Puma
|
|
80
80
|
|
81
81
|
def authenticate(env)
|
82
82
|
return true unless @auth_token
|
83
|
-
env['QUERY_STRING'].to_s.split(
|
83
|
+
env['QUERY_STRING'].to_s.split('&;').include? "token=#{@auth_token}"
|
84
84
|
end
|
85
85
|
|
86
86
|
def rack_response(status, body, content_type='application/json')
|
87
87
|
headers = {
|
88
|
-
'
|
89
|
-
'
|
88
|
+
'content-type' => content_type,
|
89
|
+
'content-length' => body.bytesize.to_s
|
90
90
|
}
|
91
91
|
|
92
92
|
[status, headers, [body]]
|
data/lib/puma/binder.rb
CHANGED
@@ -3,24 +3,15 @@
|
|
3
3
|
require 'uri'
|
4
4
|
require 'socket'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
require_relative 'const'
|
7
|
+
require_relative 'util'
|
8
|
+
require_relative 'configuration'
|
9
9
|
|
10
10
|
module Puma
|
11
11
|
|
12
12
|
if HAS_SSL
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
# Odd bug in 'pure Ruby' nio4r version 2.5.2, which installs with Ruby 2.3.
|
17
|
-
# NIO doesn't create any OpenSSL objects, but it rescues an OpenSSL error.
|
18
|
-
# The bug was that it did not require openssl.
|
19
|
-
# @todo remove when Ruby 2.3 support is dropped
|
20
|
-
#
|
21
|
-
if windows? && RbConfig::CONFIG['ruby_version'] == '2.3.0'
|
22
|
-
require 'openssl'
|
23
|
-
end
|
13
|
+
require_relative 'minissl'
|
14
|
+
require_relative 'minissl/context_builder'
|
24
15
|
end
|
25
16
|
|
26
17
|
class Binder
|
@@ -28,8 +19,8 @@ module Puma
|
|
28
19
|
|
29
20
|
RACK_VERSION = [1,6].freeze
|
30
21
|
|
31
|
-
def initialize(
|
32
|
-
@
|
22
|
+
def initialize(log_writer, conf = Configuration.new)
|
23
|
+
@log_writer = log_writer
|
33
24
|
@conf = conf
|
34
25
|
@listeners = []
|
35
26
|
@inherited_fds = {}
|
@@ -38,7 +29,7 @@ module Puma
|
|
38
29
|
|
39
30
|
@proto_env = {
|
40
31
|
"rack.version".freeze => RACK_VERSION,
|
41
|
-
"rack.errors".freeze =>
|
32
|
+
"rack.errors".freeze => log_writer.stderr,
|
42
33
|
"rack.multithread".freeze => conf.options[:max_threads] > 1,
|
43
34
|
"rack.multiprocess".freeze => conf.options[:workers] >= 1,
|
44
35
|
"rack.run_once".freeze => false,
|
@@ -51,14 +42,12 @@ module Puma
|
|
51
42
|
# infer properly.
|
52
43
|
|
53
44
|
"QUERY_STRING".freeze => "",
|
54
|
-
SERVER_PROTOCOL => HTTP_11,
|
55
45
|
SERVER_SOFTWARE => PUMA_SERVER_STRING,
|
56
46
|
GATEWAY_INTERFACE => CGI_VER
|
57
47
|
}
|
58
48
|
|
59
49
|
@envs = {}
|
60
50
|
@ios = []
|
61
|
-
localhost_authority
|
62
51
|
end
|
63
52
|
|
64
53
|
attr_reader :ios
|
@@ -80,7 +69,7 @@ module Puma
|
|
80
69
|
# @!attribute [r] connected_ports
|
81
70
|
# @version 5.0.0
|
82
71
|
def connected_ports
|
83
|
-
ios.map { |io| io.addr[1] }.uniq
|
72
|
+
t = ios.map { |io| io.addr[1] }; t.uniq!; t
|
84
73
|
end
|
85
74
|
|
86
75
|
# @version 5.0.0
|
@@ -98,7 +87,7 @@ module Puma
|
|
98
87
|
# @version 5.0.0
|
99
88
|
#
|
100
89
|
def create_activated_fds(env_hash)
|
101
|
-
@
|
90
|
+
@log_writer.debug "ENV['LISTEN_FDS'] #{ENV['LISTEN_FDS'].inspect} env_hash['LISTEN_PID'] #{env_hash['LISTEN_PID'].inspect}"
|
102
91
|
return [] unless env_hash['LISTEN_FDS'] && env_hash['LISTEN_PID'].to_i == $$
|
103
92
|
env_hash['LISTEN_FDS'].to_i.times do |index|
|
104
93
|
sock = TCPServer.for_fd(socket_activation_fd(index))
|
@@ -106,11 +95,11 @@ module Puma
|
|
106
95
|
[:unix, Socket.unpack_sockaddr_un(sock.getsockname)]
|
107
96
|
rescue ArgumentError # Try to parse as a port/ip
|
108
97
|
port, addr = Socket.unpack_sockaddr_in(sock.getsockname)
|
109
|
-
addr = "[#{addr}]" if addr
|
98
|
+
addr = "[#{addr}]" if addr&.include? ':'
|
110
99
|
[:tcp, addr, port]
|
111
100
|
end
|
112
101
|
@activated_sockets[key] = sock
|
113
|
-
@
|
102
|
+
@log_writer.debug "Registered #{key.join ':'} for activation from LISTEN_FDS"
|
114
103
|
end
|
115
104
|
["LISTEN_FDS", "LISTEN_PID"] # Signal to remove these keys from ENV
|
116
105
|
end
|
@@ -152,29 +141,30 @@ module Puma
|
|
152
141
|
end
|
153
142
|
end
|
154
143
|
|
155
|
-
def parse(binds,
|
144
|
+
def parse(binds, log_writer = nil, log_msg = 'Listening')
|
145
|
+
log_writer ||= @log_writer
|
156
146
|
binds.each do |str|
|
157
147
|
uri = URI.parse str
|
158
148
|
case uri.scheme
|
159
149
|
when "tcp"
|
160
150
|
if fd = @inherited_fds.delete(str)
|
161
151
|
io = inherit_tcp_listener uri.host, uri.port, fd
|
162
|
-
|
152
|
+
log_writer.log "* Inherited #{str}"
|
163
153
|
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
|
164
154
|
io = inherit_tcp_listener uri.host, uri.port, sock
|
165
|
-
|
155
|
+
log_writer.log "* Activated #{str}"
|
166
156
|
else
|
167
157
|
ios_len = @ios.length
|
168
158
|
params = Util.parse_query uri.query
|
169
159
|
|
170
|
-
|
160
|
+
low_latency = params.key?('low_latency') && params['low_latency'] != 'false'
|
171
161
|
backlog = params.fetch('backlog', 1024).to_i
|
172
162
|
|
173
|
-
io = add_tcp_listener uri.host, uri.port,
|
163
|
+
io = add_tcp_listener uri.host, uri.port, low_latency, backlog
|
174
164
|
|
175
165
|
@ios[ios_len..-1].each do |i|
|
176
166
|
addr = loc_addr_str i
|
177
|
-
|
167
|
+
log_writer.log "* #{log_msg} on http://#{addr}"
|
178
168
|
end
|
179
169
|
end
|
180
170
|
|
@@ -191,12 +181,12 @@ module Puma
|
|
191
181
|
if fd = @inherited_fds.delete(str)
|
192
182
|
@unix_paths << path unless abstract || File.exist?(path)
|
193
183
|
io = inherit_unix_listener path, fd
|
194
|
-
|
184
|
+
log_writer.log "* Inherited #{str}"
|
195
185
|
elsif sock = @activated_sockets.delete([ :unix, path ]) ||
|
196
186
|
@activated_sockets.delete([ :unix, File.realdirpath(path) ])
|
197
187
|
@unix_paths << path unless abstract || File.exist?(path)
|
198
188
|
io = inherit_unix_listener path, sock
|
199
|
-
|
189
|
+
log_writer.log "* Activated #{str}"
|
200
190
|
else
|
201
191
|
umask = nil
|
202
192
|
mode = nil
|
@@ -220,11 +210,12 @@ module Puma
|
|
220
210
|
|
221
211
|
@unix_paths << path unless abstract || File.exist?(path)
|
222
212
|
io = add_unix_listener path, umask, mode, backlog
|
223
|
-
|
213
|
+
log_writer.log "* #{log_msg} on #{str}"
|
224
214
|
end
|
225
215
|
|
226
216
|
@listeners << [str, io]
|
227
217
|
when "ssl"
|
218
|
+
cert_key = %w[cert key]
|
228
219
|
|
229
220
|
raise "Puma compiled without SSL support" unless HAS_SSL
|
230
221
|
|
@@ -233,49 +224,51 @@ module Puma
|
|
233
224
|
# If key and certs are not defined and localhost gem is required.
|
234
225
|
# localhost gem will be used for self signed
|
235
226
|
# Load localhost authority if not loaded.
|
236
|
-
|
227
|
+
# Ruby 3 `values_at` accepts an array, earlier do not
|
228
|
+
if params.values_at(*cert_key).all? { |v| v.to_s.empty? }
|
237
229
|
ctx = localhost_authority && localhost_authority_context
|
238
230
|
end
|
239
231
|
|
240
232
|
ctx ||=
|
241
233
|
begin
|
242
234
|
# Extract cert_pem and key_pem from options[:store] if present
|
243
|
-
|
244
|
-
if params[v]
|
235
|
+
cert_key.each do |v|
|
236
|
+
if params[v]&.start_with?('store:')
|
245
237
|
index = Integer(params.delete(v).split('store:').last)
|
246
238
|
params["#{v}_pem"] = @conf.options[:store][index]
|
247
239
|
end
|
248
240
|
end
|
249
|
-
MiniSSL::ContextBuilder.new(params, @
|
241
|
+
MiniSSL::ContextBuilder.new(params, @log_writer).context
|
250
242
|
end
|
251
243
|
|
252
244
|
if fd = @inherited_fds.delete(str)
|
253
|
-
|
245
|
+
log_writer.log "* Inherited #{str}"
|
254
246
|
io = inherit_ssl_listener fd, ctx
|
255
247
|
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
|
256
248
|
io = inherit_ssl_listener sock, ctx
|
257
|
-
|
249
|
+
log_writer.log "* Activated #{str}"
|
258
250
|
else
|
259
251
|
ios_len = @ios.length
|
260
252
|
backlog = params.fetch('backlog', 1024).to_i
|
261
|
-
|
253
|
+
low_latency = params['low_latency'] != 'false'
|
254
|
+
io = add_ssl_listener uri.host, uri.port, ctx, low_latency, backlog
|
262
255
|
|
263
256
|
@ios[ios_len..-1].each do |i|
|
264
257
|
addr = loc_addr_str i
|
265
|
-
|
258
|
+
log_writer.log "* #{log_msg} on ssl://#{addr}?#{uri.query}"
|
266
259
|
end
|
267
260
|
end
|
268
261
|
|
269
262
|
@listeners << [str, io] if io
|
270
263
|
else
|
271
|
-
|
264
|
+
log_writer.error "Invalid URI: #{str}"
|
272
265
|
end
|
273
266
|
end
|
274
267
|
|
275
268
|
# If we inherited fds but didn't use them (because of a
|
276
269
|
# configuration change), then be sure to close them.
|
277
270
|
@inherited_fds.each do |str, fd|
|
278
|
-
|
271
|
+
log_writer.log "* Closing unused inherited connection: #{str}"
|
279
272
|
|
280
273
|
begin
|
281
274
|
IO.for_fd(fd).close
|
@@ -295,7 +288,7 @@ module Puma
|
|
295
288
|
fds = @ios.map(&:to_i)
|
296
289
|
@activated_sockets.each do |key, sock|
|
297
290
|
next if fds.include? sock.to_i
|
298
|
-
|
291
|
+
log_writer.log "* Closing unused activated socket: #{key.first}://#{key[1..-1].join ':'}"
|
299
292
|
begin
|
300
293
|
sock.close
|
301
294
|
rescue SystemCallError
|
@@ -319,7 +312,7 @@ module Puma
|
|
319
312
|
local_certificates_path = File.expand_path("~/.localhost")
|
320
313
|
[File.join(local_certificates_path, "localhost.key"), File.join(local_certificates_path, "localhost.crt")]
|
321
314
|
end
|
322
|
-
MiniSSL::ContextBuilder.new({ "key" => key_path, "cert" => crt_path }, @
|
315
|
+
MiniSSL::ContextBuilder.new({ "key" => key_path, "cert" => crt_path }, @log_writer).context
|
323
316
|
end
|
324
317
|
|
325
318
|
# Tell the server to listen on host +host+, port +port+.
|
@@ -337,7 +330,7 @@ module Puma
|
|
337
330
|
return
|
338
331
|
end
|
339
332
|
|
340
|
-
host = host[1..-2] if host
|
333
|
+
host = host[1..-2] if host&.start_with? '['
|
341
334
|
tcp_server = TCPServer.new(host, port)
|
342
335
|
|
343
336
|
if optimize_for_latency
|
@@ -371,7 +364,7 @@ module Puma
|
|
371
364
|
return
|
372
365
|
end
|
373
366
|
|
374
|
-
host = host[1..-2] if host
|
367
|
+
host = host[1..-2] if host&.start_with? '['
|
375
368
|
s = TCPServer.new(host, port)
|
376
369
|
if optimize_for_latency
|
377
370
|
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
@@ -457,11 +450,14 @@ module Puma
|
|
457
450
|
|
458
451
|
def close_listeners
|
459
452
|
@listeners.each do |l, io|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
453
|
+
begin
|
454
|
+
io.close unless io.closed?
|
455
|
+
uri = URI.parse l
|
456
|
+
next unless uri.scheme == 'unix'
|
457
|
+
unix_path = "#{uri.host}#{uri.path}"
|
458
|
+
File.unlink unix_path if @unix_paths.include?(unix_path) && File.exist?(unix_path)
|
459
|
+
rescue Errno::EBADF
|
460
|
+
end
|
465
461
|
end
|
466
462
|
end
|
467
463
|
|
@@ -482,9 +478,10 @@ module Puma
|
|
482
478
|
|
483
479
|
# @!attribute [r] loopback_addresses
|
484
480
|
def loopback_addresses
|
485
|
-
Socket.ip_address_list.select do |addrinfo|
|
481
|
+
t = Socket.ip_address_list.select do |addrinfo|
|
486
482
|
addrinfo.ipv6_loopback? || addrinfo.ipv4_loopback?
|
487
|
-
end
|
483
|
+
end
|
484
|
+
t.map! { |addrinfo| addrinfo.ip_address }; t.uniq!; t
|
488
485
|
end
|
489
486
|
|
490
487
|
def loc_addr_str(io)
|
data/lib/puma/cli.rb
CHANGED
@@ -3,11 +3,11 @@
|
|
3
3
|
require 'optparse'
|
4
4
|
require 'uri'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
require_relative '../puma'
|
7
|
+
require_relative 'configuration'
|
8
|
+
require_relative 'launcher'
|
9
|
+
require_relative 'const'
|
10
|
+
require_relative 'log_writer'
|
11
11
|
|
12
12
|
module Puma
|
13
13
|
class << self
|
@@ -21,19 +21,13 @@ module Puma
|
|
21
21
|
# Handles invoke a Puma::Server in a command line style.
|
22
22
|
#
|
23
23
|
class CLI
|
24
|
-
# @deprecated 6.0.0
|
25
|
-
KEYS_NOT_TO_PERSIST_IN_STATE = Launcher::KEYS_NOT_TO_PERSIST_IN_STATE
|
26
|
-
|
27
24
|
# Create a new CLI object using +argv+ as the command line
|
28
25
|
# arguments.
|
29
26
|
#
|
30
|
-
|
31
|
-
# this object will report status on.
|
32
|
-
#
|
33
|
-
def initialize(argv, events=Events.stdio)
|
27
|
+
def initialize(argv, log_writer = LogWriter.stdio, events = Events.new)
|
34
28
|
@debug = false
|
35
29
|
@argv = argv.dup
|
36
|
-
|
30
|
+
@log_writer = log_writer
|
37
31
|
@events = events
|
38
32
|
|
39
33
|
@conf = nil
|
@@ -69,7 +63,7 @@ module Puma
|
|
69
63
|
end
|
70
64
|
end
|
71
65
|
|
72
|
-
@launcher = Puma::Launcher.new(@conf, :events => @events, :argv => argv)
|
66
|
+
@launcher = Puma::Launcher.new(@conf, :log_writer => @log_writer, :events => @events, :argv => argv)
|
73
67
|
end
|
74
68
|
|
75
69
|
attr_reader :launcher
|
@@ -83,7 +77,7 @@ module Puma
|
|
83
77
|
|
84
78
|
private
|
85
79
|
def unsupported(str)
|
86
|
-
@
|
80
|
+
@log_writer.error(str)
|
87
81
|
raise UnsupportedOption
|
88
82
|
end
|
89
83
|
|
@@ -99,7 +93,7 @@ module Puma
|
|
99
93
|
#
|
100
94
|
|
101
95
|
def setup_options
|
102
|
-
@conf = Configuration.new do |user_config, file_config|
|
96
|
+
@conf = Configuration.new({}, {events: @events}) do |user_config, file_config|
|
103
97
|
@parser = OptionParser.new do |o|
|
104
98
|
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
105
99
|
user_config.bind arg
|
@@ -150,9 +144,13 @@ module Puma
|
|
150
144
|
$LOAD_PATH.unshift(*arg.split(':'))
|
151
145
|
end
|
152
146
|
|
147
|
+
o.on "--idle-timeout SECONDS", "Number of seconds until the next request before automatic shutdown" do |arg|
|
148
|
+
user_config.idle_timeout arg
|
149
|
+
end
|
150
|
+
|
153
151
|
o.on "-p", "--port PORT", "Define the TCP port to bind to",
|
154
152
|
"Use -b for more advanced options" do |arg|
|
155
|
-
user_config.bind "tcp://#{Configuration::
|
153
|
+
user_config.bind "tcp://#{Configuration::DEFAULTS[:tcp_host]}:#{arg}"
|
156
154
|
end
|
157
155
|
|
158
156
|
o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
|
@@ -186,7 +184,7 @@ module Puma
|
|
186
184
|
end
|
187
185
|
|
188
186
|
o.on "-s", "--silent", "Do not log prompt messages other than errors" do
|
189
|
-
@
|
187
|
+
@log_writer = LogWriter.new(NullIO.new, $stderr)
|
190
188
|
end
|
191
189
|
|
192
190
|
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
|