puma 7.0.0.pre1-java → 7.0.1-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 +87 -4
- data/README.md +11 -24
- data/docs/fork_worker.md +5 -5
- data/docs/kubernetes.md +6 -4
- data/docs/restart.md +2 -2
- data/docs/signals.md +9 -9
- data/ext/puma_http11/extconf.rb +2 -17
- data/ext/puma_http11/mini_ssl.c +0 -5
- data/lib/puma/binder.rb +10 -8
- data/lib/puma/cli.rb +3 -5
- data/lib/puma/client.rb +14 -17
- data/lib/puma/cluster/worker.rb +0 -2
- data/lib/puma/cluster/worker_handle.rb +2 -3
- data/lib/puma/cluster.rb +7 -11
- data/lib/puma/commonlogger.rb +3 -3
- data/lib/puma/configuration.rb +83 -38
- data/lib/puma/const.rb +8 -7
- data/lib/puma/control_cli.rb +3 -2
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +96 -77
- data/lib/puma/error_logger.rb +3 -1
- data/lib/puma/events.rb +25 -10
- data/lib/puma/io_buffer.rb +8 -4
- data/lib/puma/launcher/bundle_pruner.rb +1 -1
- data/lib/puma/launcher.rb +28 -29
- data/lib/puma/minissl.rb +0 -1
- data/lib/puma/plugin/systemd.rb +3 -3
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/rack/urlmap.rb +1 -1
- data/lib/puma/reactor.rb +8 -4
- data/lib/puma/request.rb +22 -10
- data/lib/puma/runner.rb +8 -17
- data/lib/puma/server.rb +23 -13
- data/lib/puma/single.rb +4 -1
- data/lib/puma/thread_pool.rb +3 -14
- data/lib/puma/util.rb +0 -7
- data/lib/puma.rb +10 -0
- data/lib/rack/handler/puma.rb +2 -2
- metadata +5 -5
data/lib/puma/commonlogger.rb
CHANGED
@@ -29,13 +29,13 @@ module Puma
|
|
29
29
|
|
30
30
|
CONTENT_LENGTH = 'Content-Length' # should be lower case from app,
|
31
31
|
# Util::HeaderHash allows mixed
|
32
|
-
HTTP_VERSION = Const::HTTP_VERSION
|
33
32
|
HTTP_X_FORWARDED_FOR = Const::HTTP_X_FORWARDED_FOR
|
34
33
|
PATH_INFO = Const::PATH_INFO
|
35
34
|
QUERY_STRING = Const::QUERY_STRING
|
36
35
|
REMOTE_ADDR = Const::REMOTE_ADDR
|
37
36
|
REMOTE_USER = 'REMOTE_USER'
|
38
37
|
REQUEST_METHOD = Const::REQUEST_METHOD
|
38
|
+
SERVER_PROTOCOL = Const::SERVER_PROTOCOL
|
39
39
|
|
40
40
|
def initialize(app, logger=nil)
|
41
41
|
@app = app
|
@@ -70,7 +70,7 @@ module Puma
|
|
70
70
|
env[REQUEST_METHOD],
|
71
71
|
env[PATH_INFO],
|
72
72
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
73
|
-
env[
|
73
|
+
env[SERVER_PROTOCOL],
|
74
74
|
now - began_at ]
|
75
75
|
|
76
76
|
write(msg)
|
@@ -87,7 +87,7 @@ module Puma
|
|
87
87
|
env[REQUEST_METHOD],
|
88
88
|
env[PATH_INFO],
|
89
89
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
90
|
-
env[
|
90
|
+
env[SERVER_PROTOCOL],
|
91
91
|
status.to_s[0..3],
|
92
92
|
length,
|
93
93
|
now - began_at ]
|
data/lib/puma/configuration.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative 'plugin'
|
4
4
|
require_relative 'const'
|
5
5
|
require_relative 'dsl'
|
6
|
+
require_relative 'events'
|
6
7
|
|
7
8
|
module Puma
|
8
9
|
# A class used for storing "leveled" configuration options.
|
@@ -112,7 +113,7 @@ module Puma
|
|
112
113
|
# config = Configuration.new({}) do |user_config, file_config, default_config|
|
113
114
|
# user_config.port 3003
|
114
115
|
# end
|
115
|
-
# config.
|
116
|
+
# config.clamp
|
116
117
|
# puts config.options[:port]
|
117
118
|
# # => 3003
|
118
119
|
#
|
@@ -125,10 +126,13 @@ module Puma
|
|
125
126
|
# is done because an environment variable may have been modified while loading
|
126
127
|
# configuration files.
|
127
128
|
class Configuration
|
129
|
+
class NotLoadedError < StandardError; end
|
130
|
+
class NotClampedError < StandardError; end
|
131
|
+
|
128
132
|
DEFAULTS = {
|
129
133
|
auto_trim_time: 30,
|
130
134
|
binds: ['tcp://0.0.0.0:9292'.freeze],
|
131
|
-
|
135
|
+
fiber_per_request: !!ENV.fetch("PUMA_FIBER_PER_REQUEST", false),
|
132
136
|
debug: false,
|
133
137
|
enable_keep_alives: true,
|
134
138
|
early_hints: nil,
|
@@ -143,14 +147,14 @@ module Puma
|
|
143
147
|
# Limits how many requests a keep alive connection can make.
|
144
148
|
# The connection will be closed after it reaches `max_keep_alive`
|
145
149
|
# requests.
|
146
|
-
max_keep_alive:
|
150
|
+
max_keep_alive: 999,
|
147
151
|
max_threads: Puma.mri? ? 5 : 16,
|
148
152
|
min_threads: 0,
|
149
153
|
mode: :http,
|
150
154
|
mutate_stdout_and_stderr_to_sync_on_write: true,
|
151
155
|
out_of_band: [],
|
152
156
|
# Number of seconds for another request within a persistent session.
|
153
|
-
persistent_timeout:
|
157
|
+
persistent_timeout: ENV.fetch('PUMA_PERSISTENT_TIMEOUT', 65),
|
154
158
|
queue_requests: true,
|
155
159
|
rackup: 'config.ru'.freeze,
|
156
160
|
raise_exception_on_sigterm: true,
|
@@ -174,24 +178,31 @@ module Puma
|
|
174
178
|
def initialize(user_options={}, default_options = {}, env = ENV, &block)
|
175
179
|
default_options = self.puma_default_options(env).merge(default_options)
|
176
180
|
|
177
|
-
@
|
181
|
+
@_options = UserFileDefaultOptions.new(user_options, default_options)
|
178
182
|
@plugins = PluginLoader.new
|
179
|
-
@
|
180
|
-
@
|
181
|
-
@
|
182
|
-
|
183
|
-
|
184
|
-
default_options[:preload_app] = (@options[:workers] > 1) && Puma.forkable?
|
185
|
-
end
|
183
|
+
@events = @_options[:events] || Events.new
|
184
|
+
@hooks = {}
|
185
|
+
@user_dsl = DSL.new(@_options.user_options, self)
|
186
|
+
@file_dsl = DSL.new(@_options.file_options, self)
|
187
|
+
@default_dsl = DSL.new(@_options.default_options, self)
|
186
188
|
|
187
189
|
@puma_bundler_pruned = env.key? 'PUMA_BUNDLER_PRUNED'
|
188
190
|
|
189
191
|
if block
|
190
192
|
configure(&block)
|
191
193
|
end
|
194
|
+
|
195
|
+
@loaded = false
|
196
|
+
@clamped = false
|
192
197
|
end
|
193
198
|
|
194
|
-
attr_reader :
|
199
|
+
attr_reader :plugins, :events, :hooks
|
200
|
+
|
201
|
+
def options
|
202
|
+
raise NotClampedError, "ensure clamp is called before accessing options" unless @clamped
|
203
|
+
|
204
|
+
@_options
|
205
|
+
end
|
195
206
|
|
196
207
|
def configure
|
197
208
|
yield @user_dsl, @file_dsl, @default_dsl
|
@@ -204,7 +215,7 @@ module Puma
|
|
204
215
|
def initialize_copy(other)
|
205
216
|
@conf = nil
|
206
217
|
@cli_options = nil
|
207
|
-
@
|
218
|
+
@_options = @_options.dup
|
208
219
|
end
|
209
220
|
|
210
221
|
def flatten
|
@@ -212,7 +223,7 @@ module Puma
|
|
212
223
|
end
|
213
224
|
|
214
225
|
def flatten!
|
215
|
-
@
|
226
|
+
@_options = @_options.flatten
|
216
227
|
self
|
217
228
|
end
|
218
229
|
|
@@ -241,18 +252,20 @@ module Puma
|
|
241
252
|
end
|
242
253
|
|
243
254
|
def load
|
255
|
+
@loaded = true
|
244
256
|
config_files.each { |config_file| @file_dsl._load_from(config_file) }
|
245
|
-
|
246
|
-
@options
|
257
|
+
@_options
|
247
258
|
end
|
248
259
|
|
249
260
|
def config_files
|
250
|
-
|
261
|
+
raise NotLoadedError, "ensure load is called before accessing config_files" unless @loaded
|
262
|
+
|
263
|
+
files = @_options.all_of(:config_files)
|
251
264
|
|
252
265
|
return [] if files == ['-']
|
253
266
|
return files if files.any?
|
254
267
|
|
255
|
-
first_default_file = %W(config/puma/#{@
|
268
|
+
first_default_file = %W(config/puma/#{@_options[:environment]}.rb config/puma.rb).find do |f|
|
256
269
|
File.exist?(f)
|
257
270
|
end
|
258
271
|
|
@@ -260,9 +273,16 @@ module Puma
|
|
260
273
|
end
|
261
274
|
|
262
275
|
# Call once all configuration (included from rackup files)
|
263
|
-
# is loaded to
|
276
|
+
# is loaded to finalize defaults and lock in the configuration.
|
277
|
+
#
|
278
|
+
# This also calls load if it hasn't been called yet.
|
264
279
|
def clamp
|
265
|
-
@
|
280
|
+
load unless @loaded
|
281
|
+
set_conditional_default_options
|
282
|
+
@_options.finalize_values
|
283
|
+
@clamped = true
|
284
|
+
warn_hooks
|
285
|
+
options
|
266
286
|
end
|
267
287
|
|
268
288
|
# Injects the Configuration object into the env
|
@@ -281,11 +301,11 @@ module Puma
|
|
281
301
|
# Indicate if there is a properly configured app
|
282
302
|
#
|
283
303
|
def app_configured?
|
284
|
-
|
304
|
+
options[:app] || File.exist?(rackup)
|
285
305
|
end
|
286
306
|
|
287
307
|
def rackup
|
288
|
-
|
308
|
+
options[:rackup]
|
289
309
|
end
|
290
310
|
|
291
311
|
# Load the specified rackup file, pull options from
|
@@ -294,9 +314,9 @@ module Puma
|
|
294
314
|
def app
|
295
315
|
found = options[:app] || load_rackup
|
296
316
|
|
297
|
-
if
|
317
|
+
if options[:log_requests]
|
298
318
|
require_relative 'commonlogger'
|
299
|
-
logger =
|
319
|
+
logger = options[:custom_logger] ? options[:custom_logger] : options[:logger]
|
300
320
|
found = CommonLogger.new(found, logger)
|
301
321
|
end
|
302
322
|
|
@@ -305,7 +325,7 @@ module Puma
|
|
305
325
|
|
306
326
|
# Return which environment we're running in
|
307
327
|
def environment
|
308
|
-
|
328
|
+
options[:environment]
|
309
329
|
end
|
310
330
|
|
311
331
|
def load_plugin(name)
|
@@ -313,18 +333,19 @@ module Puma
|
|
313
333
|
end
|
314
334
|
|
315
335
|
# @param key [:Symbol] hook to run
|
316
|
-
# @param arg [Launcher, Int] `:
|
336
|
+
# @param arg [Launcher, Int] `:before_restart` passes Launcher
|
317
337
|
#
|
318
338
|
def run_hooks(key, arg, log_writer, hook_data = nil)
|
319
339
|
log_writer.debug "Running #{key} hooks"
|
320
340
|
|
321
|
-
|
341
|
+
options.all_of(key).each do |hook_options|
|
322
342
|
begin
|
323
|
-
|
324
|
-
|
325
|
-
|
343
|
+
block = hook_options[:block]
|
344
|
+
if id = hook_options[:id]
|
345
|
+
hook_data[id] ||= Hash.new
|
346
|
+
block.call arg, hook_data[id]
|
326
347
|
else
|
327
|
-
|
348
|
+
block.call arg
|
328
349
|
end
|
329
350
|
rescue => e
|
330
351
|
log_writer.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
@@ -334,7 +355,7 @@ module Puma
|
|
334
355
|
end
|
335
356
|
|
336
357
|
def final_options
|
337
|
-
|
358
|
+
options.final_options
|
338
359
|
end
|
339
360
|
|
340
361
|
def self.temp_path
|
@@ -344,6 +365,12 @@ module Puma
|
|
344
365
|
"#{Dir.tmpdir}/puma-status-#{t}-#{$$}"
|
345
366
|
end
|
346
367
|
|
368
|
+
def self.random_token
|
369
|
+
require 'securerandom' unless defined?(SecureRandom)
|
370
|
+
|
371
|
+
SecureRandom.hex(16)
|
372
|
+
end
|
373
|
+
|
347
374
|
private
|
348
375
|
|
349
376
|
def require_processor_counter
|
@@ -384,22 +411,40 @@ module Puma
|
|
384
411
|
rack_app, rack_options = rack_builder.parse_file(rackup)
|
385
412
|
rack_options = rack_options || {}
|
386
413
|
|
387
|
-
|
414
|
+
options.file_options.merge!(rack_options)
|
388
415
|
|
389
416
|
config_ru_binds = []
|
390
417
|
rack_options.each do |k, v|
|
391
418
|
config_ru_binds << v if k.to_s.start_with?("bind")
|
392
419
|
end
|
393
420
|
|
394
|
-
|
421
|
+
options.file_options[:binds] = config_ru_binds unless config_ru_binds.empty?
|
395
422
|
|
396
423
|
rack_app
|
397
424
|
end
|
398
425
|
|
399
|
-
def
|
400
|
-
|
426
|
+
def set_conditional_default_options
|
427
|
+
@_options.default_options[:preload_app] = !@_options[:prune_bundler] &&
|
428
|
+
(@_options[:workers] > 1) && Puma.forkable?
|
429
|
+
end
|
401
430
|
|
402
|
-
|
431
|
+
def warn_hooks
|
432
|
+
return if options[:workers] > 0
|
433
|
+
return if options[:silence_fork_callback_warning]
|
434
|
+
|
435
|
+
log_writer = LogWriter.stdio
|
436
|
+
@hooks.each_key do |hook|
|
437
|
+
options.all_of(hook).each do |hook_options|
|
438
|
+
next unless hook_options[:cluster_only]
|
439
|
+
|
440
|
+
log_writer.log(<<~MSG.tr("\n", " "))
|
441
|
+
Warning: The code in the `#{hook}` block will not execute
|
442
|
+
in the current Puma configuration. The `#{hook}` block only
|
443
|
+
executes in Puma's cluster mode. To fix this, either remove the
|
444
|
+
`#{hook}` call or increase Puma's worker count above zero.
|
445
|
+
MSG
|
446
|
+
end
|
447
|
+
end
|
403
448
|
end
|
404
449
|
end
|
405
450
|
end
|
data/lib/puma/const.rb
CHANGED
@@ -100,7 +100,7 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "7.0.
|
103
|
+
PUMA_VERSION = VERSION = "7.0.1"
|
104
104
|
CODE_NAME = "Romantic Warrior"
|
105
105
|
|
106
106
|
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
@@ -123,9 +123,9 @@ module Puma
|
|
123
123
|
# Indicate that we couldn't parse the request
|
124
124
|
400 => "HTTP/1.1 400 Bad Request\r\n\r\n",
|
125
125
|
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
126
|
-
404 => "HTTP/1.1 404 Not Found\r\
|
126
|
+
404 => "HTTP/1.1 404 Not Found\r\nconnection: close\r\n\r\n",
|
127
127
|
# The standard empty 408 response for requests that timed out.
|
128
|
-
408 => "HTTP/1.1 408 Request Timeout\r\
|
128
|
+
408 => "HTTP/1.1 408 Request Timeout\r\nconnection: close\r\n\r\n",
|
129
129
|
# Indicate that there was an internal error, obviously.
|
130
130
|
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n",
|
131
131
|
# Incorrect or invalid header value
|
@@ -228,6 +228,7 @@ module Puma
|
|
228
228
|
RACK_INPUT = "rack.input"
|
229
229
|
RACK_URL_SCHEME = "rack.url_scheme"
|
230
230
|
RACK_AFTER_REPLY = "rack.after_reply"
|
231
|
+
RACK_RESPONSE_FINISHED = "rack.response_finished"
|
231
232
|
PUMA_SOCKET = "puma.socket"
|
232
233
|
PUMA_CONFIG = "puma.config"
|
233
234
|
PUMA_PEERCERT = "puma.peercert"
|
@@ -250,14 +251,14 @@ module Puma
|
|
250
251
|
KEEP_ALIVE = "keep-alive"
|
251
252
|
|
252
253
|
CONTENT_LENGTH2 = "content-length"
|
253
|
-
CONTENT_LENGTH_S = "
|
254
|
+
CONTENT_LENGTH_S = "content-length: "
|
254
255
|
TRANSFER_ENCODING = "transfer-encoding"
|
255
256
|
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
256
257
|
|
257
|
-
CONNECTION_CLOSE = "
|
258
|
-
CONNECTION_KEEP_ALIVE = "
|
258
|
+
CONNECTION_CLOSE = "connection: close\r\n"
|
259
|
+
CONNECTION_KEEP_ALIVE = "connection: keep-alive\r\n"
|
259
260
|
|
260
|
-
TRANSFER_ENCODING_CHUNKED = "
|
261
|
+
TRANSFER_ENCODING_CHUNKED = "transfer-encoding: chunked\r\n"
|
261
262
|
CLOSE_CHUNKED = "0\r\n\r\n"
|
262
263
|
|
263
264
|
CHUNKED = "chunked"
|
data/lib/puma/control_cli.rb
CHANGED
@@ -128,7 +128,8 @@ module Puma
|
|
128
128
|
require_relative 'log_writer'
|
129
129
|
|
130
130
|
config = Puma::Configuration.new({ config_files: [@config_file] }, {} , env)
|
131
|
-
config.
|
131
|
+
config.clamp
|
132
|
+
|
132
133
|
@state ||= config.options[:state]
|
133
134
|
@control_url ||= config.options[:control_url]
|
134
135
|
@control_auth_token ||= config.options[:control_auth_token]
|
@@ -248,7 +249,7 @@ module Puma
|
|
248
249
|
@stdout.flush unless @stdout.sync
|
249
250
|
return
|
250
251
|
elsif sig.start_with? 'SIG'
|
251
|
-
if Signal.list.key? sig.
|
252
|
+
if Signal.list.key? sig.delete_prefix('SIG')
|
252
253
|
Process.kill sig, @pid
|
253
254
|
else
|
254
255
|
raise "Signal '#{sig}' not available'"
|