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.
@@ -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[HTTP_VERSION],
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[HTTP_VERSION],
90
+ env[SERVER_PROTOCOL],
91
91
  status.to_s[0..3],
92
92
  length,
93
93
  now - began_at ]
@@ -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.load
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
- clean_thread_locals: false,
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: 25,
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: 20,
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
- @options = UserFileDefaultOptions.new(user_options, default_options)
181
+ @_options = UserFileDefaultOptions.new(user_options, default_options)
178
182
  @plugins = PluginLoader.new
179
- @user_dsl = DSL.new(@options.user_options, self)
180
- @file_dsl = DSL.new(@options.file_options, self)
181
- @default_dsl = DSL.new(@options.default_options, self)
182
-
183
- if !@options[:prune_bundler]
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 :options, :plugins
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
- @options = @options.dup
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
- @options = @options.flatten
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
- files = @options.all_of(:config_files)
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/#{@options[:environment]}.rb config/puma.rb).find do |f|
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 flesh out any defaults
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
- @options.finalize_values
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
- @options[:app] || File.exist?(rackup)
304
+ options[:app] || File.exist?(rackup)
285
305
  end
286
306
 
287
307
  def rackup
288
- @options[:rackup]
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 @options[:log_requests]
317
+ if options[:log_requests]
298
318
  require_relative 'commonlogger'
299
- logger = @options[: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
- @options[:environment]
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] `:on_restart` passes Launcher
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
- @options.all_of(key).each do |b|
341
+ options.all_of(key).each do |hook_options|
322
342
  begin
323
- if Array === b
324
- hook_data[b[1]] ||= Hash.new
325
- b[0].call arg, hook_data[b[1]]
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
- b.call arg
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
- @options.final_options
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
- @options.file_options.merge!(rack_options)
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
- @options.file_options[:binds] = config_ru_binds unless config_ru_binds.empty?
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 self.random_token
400
- require 'securerandom' unless defined?(SecureRandom)
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
- SecureRandom.hex(16)
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.0.pre1"
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\nConnection: close\r\n\r\n",
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\nConnection: close\r\n\r\n",
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 = "Content-Length: "
254
+ CONTENT_LENGTH_S = "content-length: "
254
255
  TRANSFER_ENCODING = "transfer-encoding"
255
256
  TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
256
257
 
257
- CONNECTION_CLOSE = "Connection: close\r\n"
258
- CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
258
+ CONNECTION_CLOSE = "connection: close\r\n"
259
+ CONNECTION_KEEP_ALIVE = "connection: keep-alive\r\n"
259
260
 
260
- TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
261
+ TRANSFER_ENCODING_CHUNKED = "transfer-encoding: chunked\r\n"
261
262
  CLOSE_CHUNKED = "0\r\n\r\n"
262
263
 
263
264
  CHUNKED = "chunked"
@@ -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.load
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.sub(/\ASIG/, '')
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'"
data/lib/puma/detect.rb CHANGED
@@ -18,6 +18,8 @@ module Puma
18
18
 
19
19
  IS_LINUX = !(IS_OSX || IS_WINDOWS)
20
20
 
21
+ IS_ARM = RUBY_PLATFORM.include? 'aarch64'
22
+
21
23
  # @version 5.2.0
22
24
  IS_MRI = RUBY_ENGINE == 'ruby'
23
25