puma 5.3.2 → 5.6.8
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 +4 -4
- data/History.md +211 -11
- data/README.md +47 -6
- data/docs/architecture.md +49 -16
- data/docs/compile_options.md +4 -2
- data/docs/deployment.md +53 -67
- data/docs/plugins.md +15 -15
- data/docs/rails_dev_mode.md +2 -3
- data/docs/restart.md +6 -6
- data/docs/signals.md +11 -10
- data/docs/stats.md +8 -8
- data/docs/systemd.md +64 -67
- data/ext/puma_http11/extconf.rb +34 -6
- data/ext/puma_http11/http11_parser.c +23 -10
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/mini_ssl.c +90 -12
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +49 -47
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +38 -55
- data/ext/puma_http11/puma_http11.c +1 -1
- data/lib/puma/app/status.rb +7 -4
- data/lib/puma/binder.rb +51 -6
- data/lib/puma/cli.rb +14 -4
- data/lib/puma/client.rb +143 -25
- data/lib/puma/cluster/worker.rb +8 -18
- data/lib/puma/cluster/worker_handle.rb +4 -0
- data/lib/puma/cluster.rb +30 -24
- data/lib/puma/configuration.rb +4 -1
- data/lib/puma/const.rb +9 -8
- data/lib/puma/control_cli.rb +19 -13
- data/lib/puma/detect.rb +8 -2
- data/lib/puma/dsl.rb +111 -13
- data/lib/puma/{json.rb → json_serialization.rb} +1 -1
- data/lib/puma/launcher.rb +15 -1
- data/lib/puma/minissl/context_builder.rb +8 -6
- data/lib/puma/minissl.rb +33 -27
- data/lib/puma/null_io.rb +5 -0
- data/lib/puma/plugin.rb +2 -2
- data/lib/puma/rack/builder.rb +1 -1
- data/lib/puma/request.rb +19 -10
- data/lib/puma/runner.rb +22 -8
- data/lib/puma/server.rb +37 -29
- data/lib/puma/state_file.rb +42 -7
- data/lib/puma/thread_pool.rb +7 -5
- data/lib/puma/util.rb +20 -4
- data/lib/puma.rb +6 -4
- data/lib/rack/version_restriction.rb +15 -0
- data/tools/Dockerfile +1 -1
- metadata +8 -7
data/lib/puma/dsl.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'puma/const'
|
4
|
+
require 'puma/util'
|
4
5
|
|
5
6
|
module Puma
|
6
7
|
# The methods that are available for use inside the configuration file.
|
@@ -46,7 +47,9 @@ module Puma
|
|
46
47
|
else ''
|
47
48
|
end
|
48
49
|
|
49
|
-
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
50
|
+
ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
|
51
|
+
|
52
|
+
backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
|
50
53
|
|
51
54
|
if defined?(JRUBY_VERSION)
|
52
55
|
ssl_cipher_list = opts[:ssl_cipher_list] ?
|
@@ -55,7 +58,7 @@ module Puma
|
|
55
58
|
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
56
59
|
|
57
60
|
"ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
|
58
|
-
"&verify_mode=#{verify}#{tls_str}#{ca_additions}"
|
61
|
+
"&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
|
59
62
|
else
|
60
63
|
ssl_cipher_filter = opts[:ssl_cipher_filter] ?
|
61
64
|
"&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
|
@@ -63,8 +66,11 @@ module Puma
|
|
63
66
|
v_flags = (ary = opts[:verification_flags]) ?
|
64
67
|
"&verification_flags=#{Array(ary).join ','}" : nil
|
65
68
|
|
66
|
-
|
67
|
-
|
69
|
+
cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(opts[:cert])}" : nil
|
70
|
+
key_flags = (cert = opts[:key]) ? "&key=#{Puma::Util.escape(opts[:key])}" : nil
|
71
|
+
|
72
|
+
"ssl://#{host}:#{port}?#{cert_flags}#{key_flags}" \
|
73
|
+
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
@@ -191,7 +197,7 @@ module Puma
|
|
191
197
|
end
|
192
198
|
|
193
199
|
# Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
|
194
|
-
# accepted protocols. Multiple urls can be bound to, calling
|
200
|
+
# accepted protocols. Multiple urls can be bound to, calling +bind+ does
|
195
201
|
# not overwrite previous bindings.
|
196
202
|
#
|
197
203
|
# The default is "tcp://0.0.0.0:9292".
|
@@ -381,6 +387,13 @@ module Puma
|
|
381
387
|
@options[:rackup] ||= path.to_s
|
382
388
|
end
|
383
389
|
|
390
|
+
# Allows setting `env['rack.url_scheme']`.
|
391
|
+
# Only necessary if X-Forwarded-Proto is not being set by your proxy
|
392
|
+
# Normal values are 'http' or 'https'.
|
393
|
+
def rack_url_scheme(scheme=nil)
|
394
|
+
@options[:rack_url_scheme] = scheme
|
395
|
+
end
|
396
|
+
|
384
397
|
def early_hints(answer=true)
|
385
398
|
@options[:early_hints] = answer
|
386
399
|
end
|
@@ -429,8 +442,15 @@ module Puma
|
|
429
442
|
@options[:max_threads] = max
|
430
443
|
end
|
431
444
|
|
432
|
-
# Instead of
|
433
|
-
#
|
445
|
+
# Instead of using +bind+ and manually constructing a URI like:
|
446
|
+
#
|
447
|
+
# bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
|
448
|
+
#
|
449
|
+
# you can use the this method.
|
450
|
+
#
|
451
|
+
# When binding on localhost you don't need to specify +cert+ and +key+,
|
452
|
+
# Puma will assume you are using the +localhost+ gem and try to load the
|
453
|
+
# appropriate files.
|
434
454
|
#
|
435
455
|
# @example
|
436
456
|
# ssl_bind '127.0.0.1', '9292', {
|
@@ -440,14 +460,25 @@ module Puma
|
|
440
460
|
# verify_mode: verify_mode, # default 'none'
|
441
461
|
# verification_flags: flags, # optional, not supported by JRuby
|
442
462
|
# }
|
443
|
-
#
|
463
|
+
#
|
464
|
+
# @example Using self-signed certificate with the +localhost+ gem:
|
465
|
+
# ssl_bind '127.0.0.1', '9292'
|
466
|
+
#
|
467
|
+
# @example Alternatively, you can provide +cert_pem+ and +key_pem+:
|
468
|
+
# ssl_bind '127.0.0.1', '9292', {
|
469
|
+
# cert_pem: File.read(path_to_cert),
|
470
|
+
# key_pem: File.read(path_to_key),
|
471
|
+
# }
|
472
|
+
#
|
473
|
+
# @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
|
444
474
|
# ssl_bind '127.0.0.1', '9292', {
|
445
475
|
# keystore: path_to_keystore,
|
446
476
|
# keystore_pass: password,
|
447
477
|
# ssl_cipher_list: cipher_list, # optional
|
448
478
|
# verify_mode: verify_mode # default 'none'
|
449
479
|
# }
|
450
|
-
def ssl_bind(host, port, opts)
|
480
|
+
def ssl_bind(host, port, opts = {})
|
481
|
+
add_pem_values_to_options_store(opts)
|
451
482
|
bind self.class.ssl_bind_str(host, port, opts)
|
452
483
|
end
|
453
484
|
|
@@ -578,7 +609,7 @@ module Puma
|
|
578
609
|
# end
|
579
610
|
def after_worker_fork(&block)
|
580
611
|
@options[:after_worker_fork] ||= []
|
581
|
-
@options[:after_worker_fork]
|
612
|
+
@options[:after_worker_fork] << block
|
582
613
|
end
|
583
614
|
|
584
615
|
alias_method :after_worker_boot, :after_worker_fork
|
@@ -720,6 +751,19 @@ module Puma
|
|
720
751
|
@options[:tag] = string.to_s
|
721
752
|
end
|
722
753
|
|
754
|
+
# Change the default interval for checking workers.
|
755
|
+
#
|
756
|
+
# The default value is 5 seconds.
|
757
|
+
#
|
758
|
+
# @note Cluster mode only.
|
759
|
+
# @example
|
760
|
+
# worker_check_interval 5
|
761
|
+
# @see Puma::Cluster#check_workers
|
762
|
+
#
|
763
|
+
def worker_check_interval(interval)
|
764
|
+
@options[:worker_check_interval] = Integer(interval)
|
765
|
+
end
|
766
|
+
|
723
767
|
# Verifies that all workers have checked in to the master process within
|
724
768
|
# the given timeout. If not the worker process will be restarted. This is
|
725
769
|
# not a request timeout, it is to protect against a hung or dead process.
|
@@ -734,7 +778,7 @@ module Puma
|
|
734
778
|
#
|
735
779
|
def worker_timeout(timeout)
|
736
780
|
timeout = Integer(timeout)
|
737
|
-
min =
|
781
|
+
min = @options.fetch(:worker_check_interval, Puma::ConfigDefault::DefaultWorkerCheckInterval)
|
738
782
|
|
739
783
|
if timeout <= min
|
740
784
|
raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
|
@@ -766,6 +810,30 @@ module Puma
|
|
766
810
|
@options[:worker_shutdown_timeout] = Integer(timeout)
|
767
811
|
end
|
768
812
|
|
813
|
+
# Set the strategy for worker culling.
|
814
|
+
#
|
815
|
+
# There are two possible values:
|
816
|
+
#
|
817
|
+
# 1. **:youngest** - the youngest workers (i.e. the workers that were
|
818
|
+
# the most recently started) will be culled.
|
819
|
+
# 2. **:oldest** - the oldest workers (i.e. the workers that were started
|
820
|
+
# the longest time ago) will be culled.
|
821
|
+
#
|
822
|
+
# @note Cluster mode only.
|
823
|
+
# @example
|
824
|
+
# worker_culling_strategy :oldest
|
825
|
+
# @see Puma::Cluster#cull_workers
|
826
|
+
#
|
827
|
+
def worker_culling_strategy(strategy)
|
828
|
+
stategy = strategy.to_sym
|
829
|
+
|
830
|
+
if ![:youngest, :oldest].include?(strategy)
|
831
|
+
raise "Invalid value for worker_culling_strategy - #{stategy}"
|
832
|
+
end
|
833
|
+
|
834
|
+
@options[:worker_culling_strategy] = strategy
|
835
|
+
end
|
836
|
+
|
769
837
|
# When set to true (the default), workers accept all requests
|
770
838
|
# and queue them before passing them to the handlers.
|
771
839
|
# When set to false, each worker process accepts exactly as
|
@@ -811,7 +879,7 @@ module Puma
|
|
811
879
|
# a kernel syscall is required which for very fast rack handlers
|
812
880
|
# slows down the handling significantly.
|
813
881
|
#
|
814
|
-
# There are
|
882
|
+
# There are 5 possible values:
|
815
883
|
#
|
816
884
|
# 1. **:socket** (the default) - read the peername from the socket using the
|
817
885
|
# syscall. This is the normal behavior.
|
@@ -821,7 +889,10 @@ module Puma
|
|
821
889
|
# `set_remote_address header: "X-Real-IP"`.
|
822
890
|
# Only the first word (as separated by spaces or comma) is used, allowing
|
823
891
|
# headers such as X-Forwarded-For to be used as well.
|
824
|
-
# 4.
|
892
|
+
# 4. **proxy_protocol: :v1**- set the remote address to the value read from the
|
893
|
+
# HAproxy PROXY protocol, version 1. If the request does not have the PROXY
|
894
|
+
# protocol attached to it, will fall back to :socket
|
895
|
+
# 5. **\<Any string\>** - this allows you to hardcode remote address to any value
|
825
896
|
# you wish. Because Puma never uses this field anyway, it's format is
|
826
897
|
# entirely in your hands.
|
827
898
|
#
|
@@ -839,6 +910,13 @@ module Puma
|
|
839
910
|
if hdr = val[:header]
|
840
911
|
@options[:remote_address] = :header
|
841
912
|
@options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
|
913
|
+
elsif protocol_version = val[:proxy_protocol]
|
914
|
+
@options[:remote_address] = :proxy_protocol
|
915
|
+
protocol_version = protocol_version.downcase.to_sym
|
916
|
+
unless [:v1].include?(protocol_version)
|
917
|
+
raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
|
918
|
+
end
|
919
|
+
@options[:remote_address_proxy_protocol] = protocol_version
|
842
920
|
else
|
843
921
|
raise "Invalid value for set_remote_address - #{val.inspect}"
|
844
922
|
end
|
@@ -910,5 +988,25 @@ module Puma
|
|
910
988
|
def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
|
911
989
|
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
912
990
|
end
|
991
|
+
|
992
|
+
private
|
993
|
+
|
994
|
+
# To avoid adding cert_pem and key_pem as URI params, we store them on the
|
995
|
+
# options[:store] from where Puma binder knows how to find and extract them.
|
996
|
+
def add_pem_values_to_options_store(opts)
|
997
|
+
return if defined?(JRUBY_VERSION)
|
998
|
+
|
999
|
+
@options[:store] ||= []
|
1000
|
+
|
1001
|
+
# Store cert_pem and key_pem to options[:store] if present
|
1002
|
+
[:cert, :key].each do |v|
|
1003
|
+
opt_key = :"#{v}_pem"
|
1004
|
+
if opts[opt_key]
|
1005
|
+
index = @options[:store].length
|
1006
|
+
@options[:store] << opts[opt_key]
|
1007
|
+
opts[v] = "store:#{index}"
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
end
|
913
1011
|
end
|
914
1012
|
end
|
@@ -17,7 +17,7 @@ module Puma
|
|
17
17
|
# be particularly full-featured or fast. It just has to handle the few places
|
18
18
|
# where Puma relies on JSON serialization internally.
|
19
19
|
|
20
|
-
module
|
20
|
+
module JSONSerialization
|
21
21
|
QUOTE = /"/
|
22
22
|
BACKSLASH = /\\/
|
23
23
|
CONTROL_CHAR_TO_ESCAPE = /[\x00-\x1F]/ # As required by ECMA-404
|
data/lib/puma/launcher.rb
CHANGED
@@ -15,6 +15,7 @@ module Puma
|
|
15
15
|
# It is responsible for either launching a cluster of Puma workers or a single
|
16
16
|
# puma server.
|
17
17
|
class Launcher
|
18
|
+
# @deprecated 6.0.0
|
18
19
|
KEYS_NOT_TO_PERSIST_IN_STATE = [
|
19
20
|
:logger, :lowlevel_error_handler,
|
20
21
|
:before_worker_shutdown, :before_worker_boot, :before_worker_fork,
|
@@ -73,7 +74,7 @@ module Puma
|
|
73
74
|
|
74
75
|
generate_restart_data
|
75
76
|
|
76
|
-
if clustered? && !
|
77
|
+
if clustered? && !Puma.forkable?
|
77
78
|
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
|
78
79
|
end
|
79
80
|
|
@@ -158,6 +159,17 @@ module Puma
|
|
158
159
|
true
|
159
160
|
end
|
160
161
|
|
162
|
+
# Begin a refork if supported
|
163
|
+
def refork
|
164
|
+
if clustered? && @runner.respond_to?(:fork_worker!) && @options[:fork_worker]
|
165
|
+
@runner.fork_worker!
|
166
|
+
true
|
167
|
+
else
|
168
|
+
log "* refork called but not available."
|
169
|
+
false
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
161
173
|
# Run the server. This blocks until the server is stopped
|
162
174
|
def run
|
163
175
|
previous_env =
|
@@ -319,10 +331,12 @@ module Puma
|
|
319
331
|
log '* Pruning Bundler environment'
|
320
332
|
home = ENV['GEM_HOME']
|
321
333
|
bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
|
334
|
+
bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
|
322
335
|
with_unbundled_env do
|
323
336
|
ENV['GEM_HOME'] = home
|
324
337
|
ENV['BUNDLE_GEMFILE'] = bundle_gemfile
|
325
338
|
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
339
|
+
ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
|
326
340
|
args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':')] + @original_argv
|
327
341
|
# Ruby 2.0+ defaults to true which breaks socket activation
|
328
342
|
args += [{:close_others => false}]
|
@@ -23,17 +23,19 @@ module Puma
|
|
23
23
|
ctx.keystore_pass = params['keystore-pass']
|
24
24
|
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
|
25
25
|
else
|
26
|
-
|
27
|
-
events.error "Please specify the SSL key via 'key='"
|
26
|
+
if params['key'].nil? && params['key_pem'].nil?
|
27
|
+
events.error "Please specify the SSL key via 'key=' or 'key_pem='"
|
28
28
|
end
|
29
29
|
|
30
|
-
ctx.key = params['key']
|
30
|
+
ctx.key = params['key'] if params['key']
|
31
|
+
ctx.key_pem = params['key_pem'] if params['key_pem']
|
31
32
|
|
32
|
-
|
33
|
-
events.error "Please specify the SSL cert via 'cert='"
|
33
|
+
if params['cert'].nil? && params['cert_pem'].nil?
|
34
|
+
events.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
|
34
35
|
end
|
35
36
|
|
36
|
-
ctx.cert = params['cert']
|
37
|
+
ctx.cert = params['cert'] if params['cert']
|
38
|
+
ctx.cert_pem = params['cert_pem'] if params['cert_pem']
|
37
39
|
|
38
40
|
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
39
41
|
unless params['ca']
|
data/lib/puma/minissl.rb
CHANGED
@@ -161,30 +161,15 @@ module Puma
|
|
161
161
|
@socket.flush
|
162
162
|
end
|
163
163
|
|
164
|
-
def read_and_drop(timeout = 1)
|
165
|
-
return :timeout unless IO.select([@socket], nil, nil, timeout)
|
166
|
-
case @socket.read_nonblock(1024, exception: false)
|
167
|
-
when nil
|
168
|
-
:eof
|
169
|
-
when :wait_readable
|
170
|
-
:eagain
|
171
|
-
else
|
172
|
-
:drop
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def should_drop_bytes?
|
177
|
-
@engine.init? || !@engine.shutdown
|
178
|
-
end
|
179
|
-
|
180
164
|
def close
|
181
165
|
begin
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
166
|
+
unless @engine.shutdown
|
167
|
+
while alert_data = @engine.extract
|
168
|
+
@socket.write alert_data
|
169
|
+
end
|
170
|
+
end
|
186
171
|
rescue IOError, SystemCallError
|
187
|
-
|
172
|
+
Puma::Util.purge_interrupt_queue
|
188
173
|
# nothing
|
189
174
|
ensure
|
190
175
|
@socket.close
|
@@ -223,6 +208,15 @@ module Puma
|
|
223
208
|
def initialize
|
224
209
|
@no_tlsv1 = false
|
225
210
|
@no_tlsv1_1 = false
|
211
|
+
@key = nil
|
212
|
+
@cert = nil
|
213
|
+
@key_pem = nil
|
214
|
+
@cert_pem = nil
|
215
|
+
end
|
216
|
+
|
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
|
226
220
|
end
|
227
221
|
|
228
222
|
if IS_JRUBY
|
@@ -232,7 +226,7 @@ module Puma
|
|
232
226
|
attr_accessor :ssl_cipher_list
|
233
227
|
|
234
228
|
def keystore=(keystore)
|
235
|
-
|
229
|
+
check_file keystore, 'Keystore'
|
236
230
|
@keystore = keystore
|
237
231
|
end
|
238
232
|
|
@@ -245,27 +239,39 @@ module Puma
|
|
245
239
|
attr_reader :key
|
246
240
|
attr_reader :cert
|
247
241
|
attr_reader :ca
|
242
|
+
attr_reader :cert_pem
|
243
|
+
attr_reader :key_pem
|
248
244
|
attr_accessor :ssl_cipher_filter
|
249
245
|
attr_accessor :verification_flags
|
250
246
|
|
251
247
|
def key=(key)
|
252
|
-
|
248
|
+
check_file key, 'Key'
|
253
249
|
@key = key
|
254
250
|
end
|
255
251
|
|
256
252
|
def cert=(cert)
|
257
|
-
|
253
|
+
check_file cert, 'Cert'
|
258
254
|
@cert = cert
|
259
255
|
end
|
260
256
|
|
261
257
|
def ca=(ca)
|
262
|
-
|
258
|
+
check_file ca, 'ca'
|
263
259
|
@ca = ca
|
264
260
|
end
|
265
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
|
+
|
266
272
|
def check
|
267
|
-
raise "Key not configured"
|
268
|
-
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?
|
269
275
|
end
|
270
276
|
end
|
271
277
|
|
data/lib/puma/null_io.rb
CHANGED
data/lib/puma/plugin.rb
CHANGED
@@ -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)
|
data/lib/puma/rack/builder.rb
CHANGED
data/lib/puma/request.rb
CHANGED
@@ -51,7 +51,7 @@ module Puma
|
|
51
51
|
head = env[REQUEST_METHOD] == HEAD
|
52
52
|
|
53
53
|
env[RACK_INPUT] = body
|
54
|
-
env[RACK_URL_SCHEME]
|
54
|
+
env[RACK_URL_SCHEME] ||= default_server_port(env) == PORT_443 ? HTTPS : HTTP
|
55
55
|
|
56
56
|
if @early_hints
|
57
57
|
env[EARLY_HINTS] = lambda { |headers|
|
@@ -167,16 +167,25 @@ module Puma
|
|
167
167
|
end
|
168
168
|
|
169
169
|
ensure
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
170
|
+
begin
|
171
|
+
uncork_socket io
|
172
|
+
|
173
|
+
body.close
|
174
|
+
client.tempfile.unlink if client.tempfile
|
175
|
+
ensure
|
176
|
+
# Whatever happens, we MUST call `close` on the response body.
|
177
|
+
# Otherwise Rack::BodyProxy callbacks may not fire and lead to various state leaks
|
178
|
+
res_body.close if res_body.respond_to? :close
|
179
|
+
end
|
175
180
|
|
176
|
-
|
181
|
+
begin
|
182
|
+
after_reply.each { |o| o.call }
|
183
|
+
rescue StandardError => e
|
184
|
+
@log_writer.debug_error e
|
185
|
+
end
|
177
186
|
end
|
178
187
|
|
179
|
-
|
188
|
+
res_info[:keep_alive]
|
180
189
|
end
|
181
190
|
|
182
191
|
# @param env [Hash] see Puma::Client#env, from request
|
@@ -201,7 +210,7 @@ module Puma
|
|
201
210
|
begin
|
202
211
|
n = io.syswrite str
|
203
212
|
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
204
|
-
|
213
|
+
unless io.wait_writable WRITE_TIMEOUT
|
205
214
|
raise ConnectionError, "Socket timeout writing data"
|
206
215
|
end
|
207
216
|
|
@@ -419,7 +428,7 @@ module Puma
|
|
419
428
|
# of concurrent connections exceeds the size of the threadpool.
|
420
429
|
res_info[:keep_alive] &&= requests < @max_fast_inline ||
|
421
430
|
@thread_pool.busy_threads < @max_threads ||
|
422
|
-
!
|
431
|
+
!client.listener.to_io.wait_readable(0)
|
423
432
|
|
424
433
|
res_info[:response_hijack] = nil
|
425
434
|
|
data/lib/puma/runner.rb
CHANGED
@@ -15,6 +15,16 @@ module Puma
|
|
15
15
|
@app = nil
|
16
16
|
@control = nil
|
17
17
|
@started_at = Time.now
|
18
|
+
@wakeup = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def wakeup!
|
22
|
+
return unless @wakeup
|
23
|
+
|
24
|
+
@wakeup.write "!" unless @wakeup.closed?
|
25
|
+
|
26
|
+
rescue SystemCallError, IOError
|
27
|
+
Puma::Util.purge_interrupt_queue
|
18
28
|
end
|
19
29
|
|
20
30
|
def development?
|
@@ -59,7 +69,7 @@ module Puma
|
|
59
69
|
|
60
70
|
control.binder.parse [str], self, 'Starting control server'
|
61
71
|
|
62
|
-
control.run thread_name: '
|
72
|
+
control.run thread_name: 'ctl'
|
63
73
|
@control = control
|
64
74
|
end
|
65
75
|
|
@@ -84,12 +94,13 @@ module Puma
|
|
84
94
|
def output_header(mode)
|
85
95
|
min_t = @options[:min_threads]
|
86
96
|
max_t = @options[:max_threads]
|
97
|
+
environment = @options[:environment]
|
87
98
|
|
88
99
|
log "Puma starting in #{mode} mode..."
|
89
100
|
log "* Puma version: #{Puma::Const::PUMA_VERSION} (#{ruby_engine}) (\"#{Puma::Const::CODE_NAME}\")"
|
90
101
|
log "* Min threads: #{min_t}"
|
91
102
|
log "* Max threads: #{max_t}"
|
92
|
-
log "* Environment: #{
|
103
|
+
log "* Environment: #{environment}"
|
93
104
|
|
94
105
|
if mode == "cluster"
|
95
106
|
log "* Master PID: #{Process.pid}"
|
@@ -108,9 +119,7 @@ module Puma
|
|
108
119
|
append = @options[:redirect_append]
|
109
120
|
|
110
121
|
if stdout
|
111
|
-
|
112
|
-
raise "Cannot redirect STDOUT to #{stdout}"
|
113
|
-
end
|
122
|
+
ensure_output_directory_exists(stdout, 'STDOUT')
|
114
123
|
|
115
124
|
STDOUT.reopen stdout, (append ? "a" : "w")
|
116
125
|
STDOUT.puts "=== puma startup: #{Time.now} ==="
|
@@ -118,9 +127,7 @@ module Puma
|
|
118
127
|
end
|
119
128
|
|
120
129
|
if stderr
|
121
|
-
|
122
|
-
raise "Cannot redirect STDERR to #{stderr}"
|
123
|
-
end
|
130
|
+
ensure_output_directory_exists(stderr, 'STDERR')
|
124
131
|
|
125
132
|
STDERR.reopen stderr, (append ? "a" : "w")
|
126
133
|
STDERR.puts "=== puma startup: #{Time.now} ==="
|
@@ -159,5 +166,12 @@ module Puma
|
|
159
166
|
server.inherit_binder @launcher.binder
|
160
167
|
server
|
161
168
|
end
|
169
|
+
|
170
|
+
private
|
171
|
+
def ensure_output_directory_exists(path, io_name)
|
172
|
+
unless Dir.exist?(File.dirname(path))
|
173
|
+
raise "Cannot redirect #{io_name} to #{path}"
|
174
|
+
end
|
175
|
+
end
|
162
176
|
end
|
163
177
|
end
|