puma 5.4.0-java → 5.6.0-java
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 +4 -4
- data/History.md +96 -2
- data/LICENSE +0 -0
- data/README.md +47 -6
- data/bin/puma-wild +0 -0
- data/docs/architecture.md +49 -16
- data/docs/compile_options.md +4 -2
- data/docs/deployment.md +53 -52
- data/docs/fork_worker.md +0 -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 +0 -0
- data/docs/jungle/rc.d/README.md +0 -0
- data/docs/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +0 -0
- data/docs/nginx.md +0 -0
- 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/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/ext_help.h +0 -0
- data/ext/puma_http11/extconf.rb +12 -6
- data/ext/puma_http11/http11_parser.c +23 -10
- data/ext/puma_http11/http11_parser.h +0 -0
- data/ext/puma_http11/http11_parser.java.rl +0 -0
- data/ext/puma_http11/http11_parser.rl +0 -0
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/mini_ssl.c +54 -9
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +49 -47
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +28 -43
- data/ext/puma_http11/puma_http11.c +1 -1
- data/lib/puma/app/status.rb +0 -0
- data/lib/puma/binder.rb +46 -4
- data/lib/puma/cli.rb +14 -4
- data/lib/puma/client.rb +46 -4
- data/lib/puma/cluster/worker.rb +7 -17
- data/lib/puma/cluster/worker_handle.rb +4 -0
- data/lib/puma/cluster.rb +29 -21
- data/lib/puma/commonlogger.rb +0 -0
- data/lib/puma/configuration.rb +4 -1
- data/lib/puma/const.rb +4 -5
- data/lib/puma/control_cli.rb +1 -1
- data/lib/puma/detect.rb +8 -2
- data/lib/puma/dsl.rb +98 -11
- data/lib/puma/error_logger.rb +0 -0
- data/lib/puma/events.rb +0 -0
- data/lib/puma/io_buffer.rb +0 -0
- data/lib/puma/jruby_restart.rb +0 -0
- data/lib/puma/json_serialization.rb +0 -0
- data/lib/puma/launcher.rb +4 -1
- data/lib/puma/minissl/context_builder.rb +8 -6
- data/lib/puma/minissl.rb +24 -23
- data/lib/puma/null_io.rb +0 -0
- data/lib/puma/plugin/tmp_restart.rb +0 -0
- data/lib/puma/plugin.rb +1 -1
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/queue_close.rb +0 -0
- data/lib/puma/rack/builder.rb +0 -0
- data/lib/puma/rack/urlmap.rb +0 -0
- data/lib/puma/rack_default.rb +0 -0
- data/lib/puma/reactor.rb +0 -0
- data/lib/puma/request.rb +47 -29
- data/lib/puma/runner.rb +22 -8
- data/lib/puma/server.rb +40 -37
- data/lib/puma/single.rb +0 -0
- data/lib/puma/state_file.rb +41 -7
- data/lib/puma/systemd.rb +0 -0
- data/lib/puma/thread_pool.rb +2 -2
- data/lib/puma/util.rb +7 -0
- data/lib/puma.rb +0 -0
- data/lib/rack/handler/puma.rb +0 -0
- data/tools/Dockerfile +1 -1
- data/tools/trickletest.rb +0 -0
- metadata +6 -6
data/lib/puma/cluster.rb
CHANGED
|
@@ -108,24 +108,42 @@ module Puma
|
|
|
108
108
|
def cull_workers
|
|
109
109
|
diff = @workers.size - @options[:workers]
|
|
110
110
|
return if diff < 1
|
|
111
|
+
debug "Culling #{diff} workers"
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
workers = workers_to_cull(diff)
|
|
114
|
+
debug "Workers to cull: #{workers.inspect}"
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
debug "Workers to cull: #{workers_to_cull.inspect}"
|
|
116
|
-
|
|
117
|
-
workers_to_cull.each do |worker|
|
|
116
|
+
workers.each do |worker|
|
|
118
117
|
log "- Worker #{worker.index} (PID: #{worker.pid}) terminating"
|
|
119
118
|
worker.term
|
|
120
119
|
end
|
|
121
120
|
end
|
|
122
121
|
|
|
122
|
+
def workers_to_cull(diff)
|
|
123
|
+
workers = @workers.sort_by(&:started_at)
|
|
124
|
+
|
|
125
|
+
# In fork_worker mode, worker 0 acts as our master process.
|
|
126
|
+
# We should avoid culling it to preserve copy-on-write memory gains.
|
|
127
|
+
workers.reject! { |w| w.index == 0 } if @options[:fork_worker]
|
|
128
|
+
|
|
129
|
+
workers[cull_start_index(diff), diff]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def cull_start_index(diff)
|
|
133
|
+
case @options[:worker_culling_strategy]
|
|
134
|
+
when :oldest
|
|
135
|
+
0
|
|
136
|
+
else # :youngest
|
|
137
|
+
-diff
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
123
141
|
# @!attribute [r] next_worker_index
|
|
124
142
|
def next_worker_index
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
143
|
+
occupied_positions = @workers.map(&:index)
|
|
144
|
+
idx = 0
|
|
145
|
+
idx += 1 until !occupied_positions.include?(idx)
|
|
146
|
+
idx
|
|
129
147
|
end
|
|
130
148
|
|
|
131
149
|
def all_workers_booted?
|
|
@@ -135,7 +153,7 @@ module Puma
|
|
|
135
153
|
def check_workers
|
|
136
154
|
return if @next_check >= Time.now
|
|
137
155
|
|
|
138
|
-
@next_check = Time.now +
|
|
156
|
+
@next_check = Time.now + @options[:worker_check_interval]
|
|
139
157
|
|
|
140
158
|
timeout_workers
|
|
141
159
|
wait_workers
|
|
@@ -164,16 +182,6 @@ module Puma
|
|
|
164
182
|
].compact.min
|
|
165
183
|
end
|
|
166
184
|
|
|
167
|
-
def wakeup!
|
|
168
|
-
return unless @wakeup
|
|
169
|
-
|
|
170
|
-
begin
|
|
171
|
-
@wakeup.write "!" unless @wakeup.closed?
|
|
172
|
-
rescue SystemCallError, IOError
|
|
173
|
-
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
185
|
def worker(index, master)
|
|
178
186
|
@workers = []
|
|
179
187
|
|
|
@@ -450,7 +458,7 @@ module Puma
|
|
|
450
458
|
workers_not_booted -= 1
|
|
451
459
|
when "e"
|
|
452
460
|
# external term, see worker method, Signal.trap "SIGTERM"
|
|
453
|
-
w.
|
|
461
|
+
w.term!
|
|
454
462
|
when "t"
|
|
455
463
|
w.term unless w.term?
|
|
456
464
|
when "p"
|
data/lib/puma/commonlogger.rb
CHANGED
|
File without changes
|
data/lib/puma/configuration.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Puma
|
|
|
11
11
|
|
|
12
12
|
DefaultTCPHost = "0.0.0.0"
|
|
13
13
|
DefaultTCPPort = 9292
|
|
14
|
+
DefaultWorkerCheckInterval = 5
|
|
14
15
|
DefaultWorkerTimeout = 60
|
|
15
16
|
DefaultWorkerShutdownTimeout = 30
|
|
16
17
|
end
|
|
@@ -195,12 +196,14 @@ module Puma
|
|
|
195
196
|
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
|
196
197
|
:silence_single_worker_warning => false,
|
|
197
198
|
:mode => :http,
|
|
199
|
+
:worker_check_interval => DefaultWorkerCheckInterval,
|
|
198
200
|
:worker_timeout => DefaultWorkerTimeout,
|
|
199
201
|
:worker_boot_timeout => DefaultWorkerTimeout,
|
|
200
202
|
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
|
203
|
+
:worker_culling_strategy => :youngest,
|
|
201
204
|
:remote_address => :socket,
|
|
202
205
|
:tag => method(:infer_tag),
|
|
203
|
-
:environment => -> { ENV['RACK_ENV'] || ENV['RAILS_ENV'] ||
|
|
206
|
+
:environment => -> { ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development' },
|
|
204
207
|
:rackup => DefaultRackup,
|
|
205
208
|
:logger => STDOUT,
|
|
206
209
|
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
data/lib/puma/const.rb
CHANGED
|
@@ -100,8 +100,8 @@ module Puma
|
|
|
100
100
|
# too taxing on performance.
|
|
101
101
|
module Const
|
|
102
102
|
|
|
103
|
-
PUMA_VERSION = VERSION = "5.
|
|
104
|
-
CODE_NAME = "
|
|
103
|
+
PUMA_VERSION = VERSION = "5.6.0".freeze
|
|
104
|
+
CODE_NAME = "Birdie's Version".freeze
|
|
105
105
|
|
|
106
106
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
|
107
107
|
|
|
@@ -235,9 +235,6 @@ module Puma
|
|
|
235
235
|
|
|
236
236
|
EARLY_HINTS = "rack.early_hints".freeze
|
|
237
237
|
|
|
238
|
-
# Minimum interval to checks worker health
|
|
239
|
-
WORKER_CHECK_INTERVAL = 5
|
|
240
|
-
|
|
241
238
|
# Illegal character in the key or value of response header
|
|
242
239
|
DQUOTE = "\"".freeze
|
|
243
240
|
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
|
@@ -247,5 +244,7 @@ module Puma
|
|
|
247
244
|
|
|
248
245
|
# Banned keys of response header
|
|
249
246
|
BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
|
|
247
|
+
|
|
248
|
+
PROXY_PROTOCOL_V1_REGEX = /^PROXY (?:TCP4|TCP6|UNKNOWN) ([^\r]+)\r\n/.freeze
|
|
250
249
|
end
|
|
251
250
|
end
|
data/lib/puma/control_cli.rb
CHANGED
data/lib/puma/detect.rb
CHANGED
|
@@ -10,8 +10,10 @@ module Puma
|
|
|
10
10
|
|
|
11
11
|
IS_JRUBY = Object.const_defined? :JRUBY_VERSION
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
IS_OSX = RUBY_PLATFORM.include? 'darwin'
|
|
14
|
+
|
|
15
|
+
IS_WINDOWS = !!(RUBY_PLATFORM =~ /mswin|ming|cygwin/) ||
|
|
16
|
+
IS_JRUBY && RUBY_DESCRIPTION.include?('mswin')
|
|
15
17
|
|
|
16
18
|
# @version 5.2.0
|
|
17
19
|
IS_MRI = (RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?)
|
|
@@ -20,6 +22,10 @@ module Puma
|
|
|
20
22
|
IS_JRUBY
|
|
21
23
|
end
|
|
22
24
|
|
|
25
|
+
def self.osx?
|
|
26
|
+
IS_OSX
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
def self.windows?
|
|
24
30
|
IS_WINDOWS
|
|
25
31
|
end
|
data/lib/puma/dsl.rb
CHANGED
|
@@ -48,6 +48,8 @@ module Puma
|
|
|
48
48
|
|
|
49
49
|
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
|
50
50
|
|
|
51
|
+
backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
|
|
52
|
+
|
|
51
53
|
if defined?(JRUBY_VERSION)
|
|
52
54
|
ssl_cipher_list = opts[:ssl_cipher_list] ?
|
|
53
55
|
"&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
|
|
@@ -55,7 +57,7 @@ module Puma
|
|
|
55
57
|
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
|
56
58
|
|
|
57
59
|
"ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
|
|
58
|
-
"&verify_mode=#{verify}#{tls_str}#{ca_additions}"
|
|
60
|
+
"&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
|
|
59
61
|
else
|
|
60
62
|
ssl_cipher_filter = opts[:ssl_cipher_filter] ?
|
|
61
63
|
"&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
|
|
@@ -64,7 +66,7 @@ module Puma
|
|
|
64
66
|
"&verification_flags=#{Array(ary).join ','}" : nil
|
|
65
67
|
|
|
66
68
|
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
|
|
67
|
-
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}"
|
|
69
|
+
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
72
|
|
|
@@ -191,7 +193,7 @@ module Puma
|
|
|
191
193
|
end
|
|
192
194
|
|
|
193
195
|
# Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
|
|
194
|
-
# accepted protocols. Multiple urls can be bound to, calling
|
|
196
|
+
# accepted protocols. Multiple urls can be bound to, calling +bind+ does
|
|
195
197
|
# not overwrite previous bindings.
|
|
196
198
|
#
|
|
197
199
|
# The default is "tcp://0.0.0.0:9292".
|
|
@@ -436,8 +438,15 @@ module Puma
|
|
|
436
438
|
@options[:max_threads] = max
|
|
437
439
|
end
|
|
438
440
|
|
|
439
|
-
# Instead of
|
|
440
|
-
#
|
|
441
|
+
# Instead of using +bind+ and manually constructing a URI like:
|
|
442
|
+
#
|
|
443
|
+
# bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
|
|
444
|
+
#
|
|
445
|
+
# you can use the this method.
|
|
446
|
+
#
|
|
447
|
+
# When binding on localhost you don't need to specify +cert+ and +key+,
|
|
448
|
+
# Puma will assume you are using the +localhost+ gem and try to load the
|
|
449
|
+
# appropriate files.
|
|
441
450
|
#
|
|
442
451
|
# @example
|
|
443
452
|
# ssl_bind '127.0.0.1', '9292', {
|
|
@@ -447,14 +456,25 @@ module Puma
|
|
|
447
456
|
# verify_mode: verify_mode, # default 'none'
|
|
448
457
|
# verification_flags: flags, # optional, not supported by JRuby
|
|
449
458
|
# }
|
|
450
|
-
#
|
|
459
|
+
#
|
|
460
|
+
# @example Using self-signed certificate with the +localhost+ gem:
|
|
461
|
+
# ssl_bind '127.0.0.1', '9292'
|
|
462
|
+
#
|
|
463
|
+
# @example Alternatively, you can provide +cert_pem+ and +key_pem+:
|
|
464
|
+
# ssl_bind '127.0.0.1', '9292', {
|
|
465
|
+
# cert_pem: File.read(path_to_cert),
|
|
466
|
+
# key_pem: File.read(path_to_key),
|
|
467
|
+
# }
|
|
468
|
+
#
|
|
469
|
+
# @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
|
|
451
470
|
# ssl_bind '127.0.0.1', '9292', {
|
|
452
471
|
# keystore: path_to_keystore,
|
|
453
472
|
# keystore_pass: password,
|
|
454
473
|
# ssl_cipher_list: cipher_list, # optional
|
|
455
474
|
# verify_mode: verify_mode # default 'none'
|
|
456
475
|
# }
|
|
457
|
-
def ssl_bind(host, port, opts)
|
|
476
|
+
def ssl_bind(host, port, opts = {})
|
|
477
|
+
add_pem_values_to_options_store(opts)
|
|
458
478
|
bind self.class.ssl_bind_str(host, port, opts)
|
|
459
479
|
end
|
|
460
480
|
|
|
@@ -585,7 +605,7 @@ module Puma
|
|
|
585
605
|
# end
|
|
586
606
|
def after_worker_fork(&block)
|
|
587
607
|
@options[:after_worker_fork] ||= []
|
|
588
|
-
@options[:after_worker_fork]
|
|
608
|
+
@options[:after_worker_fork] << block
|
|
589
609
|
end
|
|
590
610
|
|
|
591
611
|
alias_method :after_worker_boot, :after_worker_fork
|
|
@@ -727,6 +747,19 @@ module Puma
|
|
|
727
747
|
@options[:tag] = string.to_s
|
|
728
748
|
end
|
|
729
749
|
|
|
750
|
+
# Change the default interval for checking workers.
|
|
751
|
+
#
|
|
752
|
+
# The default value is 5 seconds.
|
|
753
|
+
#
|
|
754
|
+
# @note Cluster mode only.
|
|
755
|
+
# @example
|
|
756
|
+
# worker_check_interval 5
|
|
757
|
+
# @see Puma::Cluster#check_workers
|
|
758
|
+
#
|
|
759
|
+
def worker_check_interval(interval)
|
|
760
|
+
@options[:worker_check_interval] = Integer(interval)
|
|
761
|
+
end
|
|
762
|
+
|
|
730
763
|
# Verifies that all workers have checked in to the master process within
|
|
731
764
|
# the given timeout. If not the worker process will be restarted. This is
|
|
732
765
|
# not a request timeout, it is to protect against a hung or dead process.
|
|
@@ -741,7 +774,7 @@ module Puma
|
|
|
741
774
|
#
|
|
742
775
|
def worker_timeout(timeout)
|
|
743
776
|
timeout = Integer(timeout)
|
|
744
|
-
min =
|
|
777
|
+
min = @options.fetch(:worker_check_interval, Puma::ConfigDefault::DefaultWorkerCheckInterval)
|
|
745
778
|
|
|
746
779
|
if timeout <= min
|
|
747
780
|
raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
|
|
@@ -773,6 +806,30 @@ module Puma
|
|
|
773
806
|
@options[:worker_shutdown_timeout] = Integer(timeout)
|
|
774
807
|
end
|
|
775
808
|
|
|
809
|
+
# Set the strategy for worker culling.
|
|
810
|
+
#
|
|
811
|
+
# There are two possible values:
|
|
812
|
+
#
|
|
813
|
+
# 1. **:youngest** - the youngest workers (i.e. the workers that were
|
|
814
|
+
# the most recently started) will be culled.
|
|
815
|
+
# 2. **:oldest** - the oldest workers (i.e. the workers that were started
|
|
816
|
+
# the longest time ago) will be culled.
|
|
817
|
+
#
|
|
818
|
+
# @note Cluster mode only.
|
|
819
|
+
# @example
|
|
820
|
+
# worker_culling_strategy :oldest
|
|
821
|
+
# @see Puma::Cluster#cull_workers
|
|
822
|
+
#
|
|
823
|
+
def worker_culling_strategy(strategy)
|
|
824
|
+
stategy = strategy.to_sym
|
|
825
|
+
|
|
826
|
+
if ![:youngest, :oldest].include?(strategy)
|
|
827
|
+
raise "Invalid value for worker_culling_strategy - #{stategy}"
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
@options[:worker_culling_strategy] = strategy
|
|
831
|
+
end
|
|
832
|
+
|
|
776
833
|
# When set to true (the default), workers accept all requests
|
|
777
834
|
# and queue them before passing them to the handlers.
|
|
778
835
|
# When set to false, each worker process accepts exactly as
|
|
@@ -818,7 +875,7 @@ module Puma
|
|
|
818
875
|
# a kernel syscall is required which for very fast rack handlers
|
|
819
876
|
# slows down the handling significantly.
|
|
820
877
|
#
|
|
821
|
-
# There are
|
|
878
|
+
# There are 5 possible values:
|
|
822
879
|
#
|
|
823
880
|
# 1. **:socket** (the default) - read the peername from the socket using the
|
|
824
881
|
# syscall. This is the normal behavior.
|
|
@@ -828,7 +885,10 @@ module Puma
|
|
|
828
885
|
# `set_remote_address header: "X-Real-IP"`.
|
|
829
886
|
# Only the first word (as separated by spaces or comma) is used, allowing
|
|
830
887
|
# headers such as X-Forwarded-For to be used as well.
|
|
831
|
-
# 4.
|
|
888
|
+
# 4. **proxy_protocol: :v1**- set the remote address to the value read from the
|
|
889
|
+
# HAproxy PROXY protocol, version 1. If the request does not have the PROXY
|
|
890
|
+
# protocol attached to it, will fall back to :socket
|
|
891
|
+
# 5. **\<Any string\>** - this allows you to hardcode remote address to any value
|
|
832
892
|
# you wish. Because Puma never uses this field anyway, it's format is
|
|
833
893
|
# entirely in your hands.
|
|
834
894
|
#
|
|
@@ -846,6 +906,13 @@ module Puma
|
|
|
846
906
|
if hdr = val[:header]
|
|
847
907
|
@options[:remote_address] = :header
|
|
848
908
|
@options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
|
|
909
|
+
elsif protocol_version = val[:proxy_protocol]
|
|
910
|
+
@options[:remote_address] = :proxy_protocol
|
|
911
|
+
protocol_version = protocol_version.downcase.to_sym
|
|
912
|
+
unless [:v1].include?(protocol_version)
|
|
913
|
+
raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
|
|
914
|
+
end
|
|
915
|
+
@options[:remote_address_proxy_protocol] = protocol_version
|
|
849
916
|
else
|
|
850
917
|
raise "Invalid value for set_remote_address - #{val.inspect}"
|
|
851
918
|
end
|
|
@@ -917,5 +984,25 @@ module Puma
|
|
|
917
984
|
def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
|
|
918
985
|
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
|
919
986
|
end
|
|
987
|
+
|
|
988
|
+
private
|
|
989
|
+
|
|
990
|
+
# To avoid adding cert_pem and key_pem as URI params, we store them on the
|
|
991
|
+
# options[:store] from where Puma binder knows how to find and extract them.
|
|
992
|
+
def add_pem_values_to_options_store(opts)
|
|
993
|
+
return if defined?(JRUBY_VERSION)
|
|
994
|
+
|
|
995
|
+
@options[:store] ||= []
|
|
996
|
+
|
|
997
|
+
# Store cert_pem and key_pem to options[:store] if present
|
|
998
|
+
[:cert, :key].each do |v|
|
|
999
|
+
opt_key = :"#{v}_pem"
|
|
1000
|
+
if opts[opt_key]
|
|
1001
|
+
index = @options[:store].length
|
|
1002
|
+
@options[:store] << opts[opt_key]
|
|
1003
|
+
opts[v] = "store:#{index}"
|
|
1004
|
+
end
|
|
1005
|
+
end
|
|
1006
|
+
end
|
|
920
1007
|
end
|
|
921
1008
|
end
|
data/lib/puma/error_logger.rb
CHANGED
|
File without changes
|
data/lib/puma/events.rb
CHANGED
|
File without changes
|
data/lib/puma/io_buffer.rb
CHANGED
|
File without changes
|
data/lib/puma/jruby_restart.rb
CHANGED
|
File without changes
|
|
File without changes
|
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
|
|
|
@@ -319,10 +320,12 @@ module Puma
|
|
|
319
320
|
log '* Pruning Bundler environment'
|
|
320
321
|
home = ENV['GEM_HOME']
|
|
321
322
|
bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
|
|
323
|
+
bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
|
|
322
324
|
with_unbundled_env do
|
|
323
325
|
ENV['GEM_HOME'] = home
|
|
324
326
|
ENV['BUNDLE_GEMFILE'] = bundle_gemfile
|
|
325
327
|
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
|
328
|
+
ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
|
|
326
329
|
args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':')] + @original_argv
|
|
327
330
|
# Ruby 2.0+ defaults to true which breaks socket activation
|
|
328
331
|
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 @socket.wait_readable(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,10 @@ 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
|
|
226
215
|
end
|
|
227
216
|
|
|
228
217
|
if IS_JRUBY
|
|
@@ -245,6 +234,8 @@ module Puma
|
|
|
245
234
|
attr_reader :key
|
|
246
235
|
attr_reader :cert
|
|
247
236
|
attr_reader :ca
|
|
237
|
+
attr_reader :cert_pem
|
|
238
|
+
attr_reader :key_pem
|
|
248
239
|
attr_accessor :ssl_cipher_filter
|
|
249
240
|
attr_accessor :verification_flags
|
|
250
241
|
|
|
@@ -263,9 +254,19 @@ module Puma
|
|
|
263
254
|
@ca = ca
|
|
264
255
|
end
|
|
265
256
|
|
|
257
|
+
def cert_pem=(cert_pem)
|
|
258
|
+
raise ArgumentError, "'cert_pem' is not a String" unless cert_pem.is_a? String
|
|
259
|
+
@cert_pem = cert_pem
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def key_pem=(key_pem)
|
|
263
|
+
raise ArgumentError, "'key_pem' is not a String" unless key_pem.is_a? String
|
|
264
|
+
@key_pem = key_pem
|
|
265
|
+
end
|
|
266
|
+
|
|
266
267
|
def check
|
|
267
|
-
raise "Key not configured"
|
|
268
|
-
raise "Cert not configured"
|
|
268
|
+
raise "Key not configured" if @key.nil? && @key_pem.nil?
|
|
269
|
+
raise "Cert not configured" if @cert.nil? && @cert_pem.nil?
|
|
269
270
|
end
|
|
270
271
|
end
|
|
271
272
|
|
data/lib/puma/null_io.rb
CHANGED
|
File without changes
|
|
File without changes
|
data/lib/puma/plugin.rb
CHANGED
data/lib/puma/puma_http11.jar
CHANGED
|
Binary file
|
data/lib/puma/queue_close.rb
CHANGED
|
File without changes
|
data/lib/puma/rack/builder.rb
CHANGED
|
File without changes
|
data/lib/puma/rack/urlmap.rb
CHANGED
|
File without changes
|
data/lib/puma/rack_default.rb
CHANGED
|
File without changes
|
data/lib/puma/reactor.rb
CHANGED
|
File without changes
|
data/lib/puma/request.rb
CHANGED
|
@@ -46,11 +46,7 @@ module Puma
|
|
|
46
46
|
env[HIJACK_P] = true
|
|
47
47
|
env[HIJACK] = client
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
head = env[REQUEST_METHOD] == HEAD
|
|
52
|
-
|
|
53
|
-
env[RACK_INPUT] = body
|
|
49
|
+
env[RACK_INPUT] = client.body
|
|
54
50
|
env[RACK_URL_SCHEME] ||= default_server_port(env) == PORT_443 ? HTTPS : HTTP
|
|
55
51
|
|
|
56
52
|
if @early_hints
|
|
@@ -69,36 +65,58 @@ module Puma
|
|
|
69
65
|
# A rack extension. If the app writes #call'ables to this
|
|
70
66
|
# array, we will invoke them when the request is done.
|
|
71
67
|
#
|
|
72
|
-
|
|
68
|
+
env[RACK_AFTER_REPLY] = []
|
|
73
69
|
|
|
74
70
|
begin
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
status, headers, res_body = @thread_pool.with_force_shutdown do
|
|
72
|
+
@app.call(env)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
return :async if client.hijacked
|
|
76
|
+
|
|
77
|
+
status = status.to_i
|
|
78
|
+
|
|
79
|
+
if status == -1
|
|
80
|
+
unless headers.empty? and res_body == []
|
|
81
|
+
raise "async response must have empty headers and body"
|
|
78
82
|
end
|
|
79
83
|
|
|
80
|
-
return :async
|
|
84
|
+
return :async
|
|
85
|
+
end
|
|
86
|
+
rescue ThreadPool::ForceShutdown => e
|
|
87
|
+
@events.unknown_error e, client, "Rack app"
|
|
88
|
+
@events.log "Detected force shutdown of a thread"
|
|
81
89
|
|
|
82
|
-
|
|
90
|
+
status, headers, res_body = lowlevel_error(e, env, 503)
|
|
91
|
+
rescue Exception => e
|
|
92
|
+
@events.unknown_error e, client, "Rack app"
|
|
83
93
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
raise "async response must have empty headers and body"
|
|
87
|
-
end
|
|
94
|
+
status, headers, res_body = lowlevel_error(e, env, 500)
|
|
95
|
+
end
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
rescue ThreadPool::ForceShutdown => e
|
|
92
|
-
@events.unknown_error e, client, "Rack app"
|
|
93
|
-
@events.log "Detected force shutdown of a thread"
|
|
97
|
+
write_response(status, headers, res_body, lines, requests, client)
|
|
98
|
+
end
|
|
94
99
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
# Does the actual response writing for Request#handle_request and Server#client_error
|
|
101
|
+
#
|
|
102
|
+
# @param status [Integer] the status returned by the Rack application
|
|
103
|
+
# @param headers [Hash] the headers returned by the Rack application
|
|
104
|
+
# @param res_body [Array] the body returned by the Rack application
|
|
105
|
+
# @param lines [Puma::IOBuffer] modified in place
|
|
106
|
+
# @param requests [Integer] number of inline requests handled
|
|
107
|
+
# @param client [Puma::Client]
|
|
108
|
+
# @return [Boolean,:async]
|
|
109
|
+
def write_response(status, headers, res_body, lines, requests, client)
|
|
110
|
+
env = client.env
|
|
111
|
+
io = client.io
|
|
98
112
|
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
return false if closed_socket?(io)
|
|
114
|
+
lines.clear
|
|
101
115
|
|
|
116
|
+
head = env[REQUEST_METHOD] == HEAD
|
|
117
|
+
after_reply = env[RACK_AFTER_REPLY] || []
|
|
118
|
+
|
|
119
|
+
begin
|
|
102
120
|
res_info = {}
|
|
103
121
|
res_info[:content_length] = nil
|
|
104
122
|
res_info[:no_body] = head
|
|
@@ -149,9 +167,9 @@ module Puma
|
|
|
149
167
|
res_body.each do |part|
|
|
150
168
|
next if part.bytesize.zero?
|
|
151
169
|
if chunked
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
170
|
+
fast_write io, (part.bytesize.to_s(16) << line_ending)
|
|
171
|
+
fast_write io, part # part may have different encoding
|
|
172
|
+
fast_write io, line_ending
|
|
155
173
|
else
|
|
156
174
|
fast_write io, part
|
|
157
175
|
end
|
|
@@ -169,7 +187,7 @@ module Puma
|
|
|
169
187
|
ensure
|
|
170
188
|
uncork_socket io
|
|
171
189
|
|
|
172
|
-
body.close
|
|
190
|
+
client.body.close if client.body
|
|
173
191
|
client.tempfile.unlink if client.tempfile
|
|
174
192
|
res_body.close if res_body.respond_to? :close
|
|
175
193
|
|