puma 6.0.2 → 6.4.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +213 -7
  3. data/LICENSE +0 -0
  4. data/README.md +59 -13
  5. data/bin/puma-wild +0 -0
  6. data/docs/architecture.md +0 -0
  7. data/docs/compile_options.md +0 -0
  8. data/docs/deployment.md +0 -0
  9. data/docs/fork_worker.md +0 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +12 -0
  17. data/docs/nginx.md +0 -0
  18. data/docs/plugins.md +0 -0
  19. data/docs/rails_dev_mode.md +0 -0
  20. data/docs/restart.md +1 -0
  21. data/docs/signals.md +0 -0
  22. data/docs/stats.md +0 -0
  23. data/docs/systemd.md +3 -6
  24. data/docs/testing_benchmarks_local_files.md +0 -0
  25. data/docs/testing_test_rackup_ci_files.md +0 -0
  26. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  27. data/ext/puma_http11/ext_help.h +0 -0
  28. data/ext/puma_http11/extconf.rb +5 -1
  29. data/ext/puma_http11/http11_parser.c +0 -0
  30. data/ext/puma_http11/http11_parser.h +0 -0
  31. data/ext/puma_http11/http11_parser.java.rl +0 -0
  32. data/ext/puma_http11/http11_parser.rl +0 -0
  33. data/ext/puma_http11/http11_parser_common.rl +0 -0
  34. data/ext/puma_http11/mini_ssl.c +96 -9
  35. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/Http11.java +0 -0
  37. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +0 -0
  38. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +2 -1
  39. data/ext/puma_http11/puma_http11.c +0 -0
  40. data/lib/puma/app/status.rb +1 -1
  41. data/lib/puma/binder.rb +14 -11
  42. data/lib/puma/cli.rb +5 -1
  43. data/lib/puma/client.rb +77 -16
  44. data/lib/puma/cluster/worker.rb +5 -0
  45. data/lib/puma/cluster/worker_handle.rb +0 -0
  46. data/lib/puma/cluster.rb +71 -10
  47. data/lib/puma/commonlogger.rb +21 -14
  48. data/lib/puma/configuration.rb +6 -4
  49. data/lib/puma/const.rb +58 -9
  50. data/lib/puma/control_cli.rb +12 -5
  51. data/lib/puma/detect.rb +5 -4
  52. data/lib/puma/dsl.rb +157 -7
  53. data/lib/puma/error_logger.rb +2 -1
  54. data/lib/puma/events.rb +0 -0
  55. data/lib/puma/io_buffer.rb +0 -0
  56. data/lib/puma/jruby_restart.rb +0 -0
  57. data/lib/puma/json_serialization.rb +0 -0
  58. data/lib/puma/launcher/bundle_pruner.rb +0 -0
  59. data/lib/puma/launcher.rb +9 -22
  60. data/lib/puma/log_writer.rb +14 -4
  61. data/lib/puma/minissl/context_builder.rb +3 -0
  62. data/lib/puma/minissl.rb +22 -0
  63. data/lib/puma/null_io.rb +16 -2
  64. data/lib/puma/plugin/systemd.rb +90 -0
  65. data/lib/puma/plugin/tmp_restart.rb +0 -0
  66. data/lib/puma/plugin.rb +0 -0
  67. data/lib/puma/rack/builder.rb +2 -2
  68. data/lib/puma/rack/urlmap.rb +1 -1
  69. data/lib/puma/rack_default.rb +18 -3
  70. data/lib/puma/reactor.rb +16 -7
  71. data/lib/puma/request.rb +91 -64
  72. data/lib/puma/runner.rb +13 -2
  73. data/lib/puma/sd_notify.rb +149 -0
  74. data/lib/puma/server.rb +91 -27
  75. data/lib/puma/single.rb +2 -0
  76. data/lib/puma/state_file.rb +2 -2
  77. data/lib/puma/thread_pool.rb +41 -3
  78. data/lib/puma/util.rb +0 -0
  79. data/lib/puma.rb +0 -0
  80. data/lib/rack/handler/puma.rb +113 -86
  81. data/tools/Dockerfile +2 -2
  82. data/tools/trickletest.rb +0 -0
  83. metadata +5 -4
  84. data/lib/puma/systemd.rb +0 -47
data/lib/puma/server.rb CHANGED
@@ -15,7 +15,6 @@ require_relative 'request'
15
15
 
16
16
  require 'socket'
17
17
  require 'io/wait' unless Puma::HAS_NATIVE_IO_WAIT
18
- require 'forwardable'
19
18
 
20
19
  module Puma
21
20
 
@@ -32,7 +31,6 @@ module Puma
32
31
  class Server
33
32
  include Puma::Const
34
33
  include Request
35
- extend Forwardable
36
34
 
37
35
  attr_reader :thread
38
36
  attr_reader :log_writer
@@ -48,10 +46,7 @@ module Puma
48
46
  attr_accessor :app
49
47
  attr_accessor :binder
50
48
 
51
- def_delegators :@binder, :add_tcp_listener, :add_ssl_listener,
52
- :add_unix_listener, :connected_ports
53
-
54
- ThreadLocalKey = :puma_server
49
+ THREAD_LOCAL_KEY = :puma_server
55
50
 
56
51
  # Create a server for the rack app +app+.
57
52
  #
@@ -86,15 +81,31 @@ module Puma
86
81
  UserFileDefaultOptions.new(options, Configuration::DEFAULTS)
87
82
  end
88
83
 
89
- @log_writer = @options.fetch :log_writer, LogWriter.stdio
90
- @early_hints = @options[:early_hints]
91
- @first_data_timeout = @options[:first_data_timeout]
92
- @min_threads = @options[:min_threads]
93
- @max_threads = @options[:max_threads]
94
- @persistent_timeout = @options[:persistent_timeout]
95
- @queue_requests = @options[:queue_requests]
96
- @max_fast_inline = @options[:max_fast_inline]
97
- @io_selector_backend = @options[:io_selector_backend]
84
+ @clustered = (@options.fetch :workers, 0) > 0
85
+ @worker_write = @options[:worker_write]
86
+ @log_writer = @options.fetch :log_writer, LogWriter.stdio
87
+ @early_hints = @options[:early_hints]
88
+ @first_data_timeout = @options[:first_data_timeout]
89
+ @persistent_timeout = @options[:persistent_timeout]
90
+ @idle_timeout = @options[:idle_timeout]
91
+ @min_threads = @options[:min_threads]
92
+ @max_threads = @options[:max_threads]
93
+ @queue_requests = @options[:queue_requests]
94
+ @max_fast_inline = @options[:max_fast_inline]
95
+ @io_selector_backend = @options[:io_selector_backend]
96
+ @http_content_length_limit = @options[:http_content_length_limit]
97
+
98
+ # make this a hash, since we prefer `key?` over `include?`
99
+ @supported_http_methods =
100
+ if @options[:supported_http_methods] == :any
101
+ :any
102
+ else
103
+ if (ary = @options[:supported_http_methods])
104
+ ary
105
+ else
106
+ SUPPORTED_HTTP_METHODS
107
+ end.sort.product([nil]).to_h.freeze
108
+ end
98
109
 
99
110
  temp = !!(@options[:environment] =~ /\A(development|test)\z/)
100
111
  @leak_stack_on_error = @options[:environment] ? temp : true
@@ -108,6 +119,8 @@ module Puma
108
119
  @precheck_closing = true
109
120
 
110
121
  @requests_count = 0
122
+
123
+ @idle_timeout_reached = false
111
124
  end
112
125
 
113
126
  def inherit_binder(bind)
@@ -117,7 +130,7 @@ module Puma
117
130
  class << self
118
131
  # @!attribute [r] current
119
132
  def current
120
- Thread.current[ThreadLocalKey]
133
+ Thread.current[THREAD_LOCAL_KEY]
121
134
  end
122
135
 
123
136
  # :nodoc:
@@ -317,8 +330,28 @@ module Puma
317
330
 
318
331
  while @status == :run || (drain && shutting_down?)
319
332
  begin
320
- ios = IO.select sockets, nil, nil, (shutting_down? ? 0 : nil)
321
- break unless ios
333
+ ios = IO.select sockets, nil, nil, (shutting_down? ? 0 : @idle_timeout)
334
+ unless ios
335
+ unless shutting_down?
336
+ @idle_timeout_reached = true
337
+
338
+ if @clustered
339
+ @worker_write << "i#{Process.pid}\n" rescue nil
340
+ next
341
+ else
342
+ @log_writer.log "- Idle timeout reached"
343
+ @status = :stop
344
+ end
345
+ end
346
+
347
+ break
348
+ end
349
+
350
+ if @idle_timeout_reached && @clustered
351
+ @idle_timeout_reached = false
352
+ @worker_write << "i#{Process.pid}\n" rescue nil
353
+ end
354
+
322
355
  ios.first.each do |sock|
323
356
  if sock == check
324
357
  break if handle_check
@@ -334,6 +367,7 @@ module Puma
334
367
  drain += 1 if shutting_down?
335
368
  pool << Client.new(io, @binder.env(sock)).tap { |c|
336
369
  c.listener = sock
370
+ c.http_content_length_limit = @http_content_length_limit
337
371
  c.send(addr_send_name, addr_value) if addr_value
338
372
  }
339
373
  end
@@ -353,6 +387,7 @@ module Puma
353
387
  @queue_requests = false
354
388
  @reactor.shutdown
355
389
  end
390
+
356
391
  graceful_shutdown if @status == :stop || @status == :restart
357
392
  rescue Exception => e
358
393
  @log_writer.unknown_error e, nil, "Exception handling servers"
@@ -402,7 +437,7 @@ module Puma
402
437
  # Return true if one or more requests were processed.
403
438
  def process_client(client)
404
439
  # Advertise this server into the thread
405
- Thread.current[ThreadLocalKey] = self
440
+ Thread.current[THREAD_LOCAL_KEY] = self
406
441
 
407
442
  clean_thread_locals = @options[:clean_thread_locals]
408
443
  close_socket = true
@@ -462,7 +497,7 @@ module Puma
462
497
  end
463
498
  true
464
499
  rescue StandardError => e
465
- client_error(e, client)
500
+ client_error(e, client, requests)
466
501
  # The ensure tries to close +client+ down
467
502
  requests > 0
468
503
  ensure
@@ -490,22 +525,22 @@ module Puma
490
525
  # :nocov:
491
526
 
492
527
  # Handle various error types thrown by Client I/O operations.
493
- def client_error(e, client)
528
+ def client_error(e, client, requests = 1)
494
529
  # Swallow, do not log
495
530
  return if [ConnectionError, EOFError].include?(e.class)
496
531
 
497
- lowlevel_error(e, client.env)
498
532
  case e
499
533
  when MiniSSL::SSLError
534
+ lowlevel_error(e, client.env)
500
535
  @log_writer.ssl_error e, client.io
501
536
  when HttpParserError
502
- client.write_error(400)
537
+ response_to_error(client, requests, e, 400)
503
538
  @log_writer.parse_error e, client
504
539
  when HttpParserError501
505
- client.write_error(501)
540
+ response_to_error(client, requests, e, 501)
506
541
  @log_writer.parse_error e, client
507
542
  else
508
- client.write_error(500)
543
+ response_to_error(client, requests, e, 500)
509
544
  @log_writer.unknown_error e, nil, "Read"
510
545
  end
511
546
  end
@@ -527,10 +562,17 @@ module Puma
527
562
  backtrace = e.backtrace.nil? ? '<no backtrace available>' : e.backtrace.join("\n")
528
563
  [status, {}, ["Puma caught this error: #{e.message} (#{e.class})\n#{backtrace}"]]
529
564
  else
530
- [status, {}, ["An unhandled lowlevel error occurred. The application logs may have details.\n"]]
565
+ [status, {}, [""]]
531
566
  end
532
567
  end
533
568
 
569
+ def response_to_error(client, requests, err, status_code)
570
+ status, headers, res_body = lowlevel_error(err, client.env, status_code)
571
+ prepare_response(status, headers, res_body, requests, client)
572
+ client.write_error(status_code)
573
+ end
574
+ private :response_to_error
575
+
534
576
  # Wait for all outstanding requests to finish.
535
577
  #
536
578
  def graceful_shutdown
@@ -564,7 +606,7 @@ module Puma
564
606
 
565
607
  def notify_safely(message)
566
608
  @notify << message
567
- rescue IOError, NoMethodError, Errno::EPIPE
609
+ rescue IOError, NoMethodError, Errno::EPIPE, Errno::EBADF
568
610
  # The server, in another thread, is shutting down
569
611
  Puma::Util.purge_interrupt_queue
570
612
  rescue RuntimeError => e
@@ -609,5 +651,27 @@ module Puma
609
651
  def stats
610
652
  STAT_METHODS.map {|name| [name, send(name) || 0]}.to_h
611
653
  end
654
+
655
+ # below are 'delegations' to binder
656
+ # remove in Puma 7?
657
+
658
+
659
+ def add_tcp_listener(host, port, optimize_for_latency = true, backlog = 1024)
660
+ @binder.add_tcp_listener host, port, optimize_for_latency, backlog
661
+ end
662
+
663
+ def add_ssl_listener(host, port, ctx, optimize_for_latency = true,
664
+ backlog = 1024)
665
+ @binder.add_ssl_listener host, port, ctx, optimize_for_latency, backlog
666
+ end
667
+
668
+ def add_unix_listener(path, umask = nil, mode = nil, backlog = 1024)
669
+ @binder.add_unix_listener path, umask, mode, backlog
670
+ end
671
+
672
+ # @!attribute [r] connected_ports
673
+ def connected_ports
674
+ @binder.connected_ports
675
+ end
612
676
  end
613
677
  end
data/lib/puma/single.rb CHANGED
@@ -57,6 +57,8 @@ module Puma
57
57
 
58
58
  @events.fire_on_booted!
59
59
 
60
+ debug_loaded_extensions("Loaded Extensions:") if @log_writer.debug?
61
+
60
62
  begin
61
63
  server_thread.join
62
64
  rescue Interrupt
@@ -56,11 +56,11 @@ module Puma
56
56
  end
57
57
 
58
58
  ALLOWED_FIELDS.each do |f|
59
- define_method f do
59
+ define_method f.to_sym do
60
60
  @options[f]
61
61
  end
62
62
 
63
- define_method "#{f}=" do |v|
63
+ define_method :"#{f}=" do |v|
64
64
  @options[f] = v
65
65
  end
66
66
  end
@@ -44,9 +44,15 @@ module Puma
44
44
  @name = name
45
45
  @min = Integer(options[:min_threads])
46
46
  @max = Integer(options[:max_threads])
47
+ # Not an 'exposed' option, options[:pool_shutdown_grace_time] is used in CI
48
+ # to shorten @shutdown_grace_time from SHUTDOWN_GRACE_TIME. Parallel CI
49
+ # makes stubbing constants difficult.
50
+ @shutdown_grace_time = Float(options[:pool_shutdown_grace_time] || SHUTDOWN_GRACE_TIME)
47
51
  @block = block
48
52
  @out_of_band = options[:out_of_band]
49
53
  @clean_thread_locals = options[:clean_thread_locals]
54
+ @before_thread_start = options[:before_thread_start]
55
+ @before_thread_exit = options[:before_thread_exit]
50
56
  @reaping_time = options[:reaping_time]
51
57
  @auto_trim_time = options[:auto_trim_time]
52
58
 
@@ -103,6 +109,7 @@ module Puma
103
109
  def spawn_thread
104
110
  @spawned += 1
105
111
 
112
+ trigger_before_thread_start_hooks
106
113
  th = Thread.new(@spawned) do |spawned|
107
114
  Puma.set_thread_name '%s tp %03i' % [@name, spawned]
108
115
  todo = @todo
@@ -121,6 +128,7 @@ module Puma
121
128
  @spawned -= 1
122
129
  @workers.delete th
123
130
  not_full.signal
131
+ trigger_before_thread_exit_hooks
124
132
  Thread.exit
125
133
  end
126
134
 
@@ -158,6 +166,36 @@ module Puma
158
166
 
159
167
  private :spawn_thread
160
168
 
169
+ def trigger_before_thread_start_hooks
170
+ return unless @before_thread_start&.any?
171
+
172
+ @before_thread_start.each do |b|
173
+ begin
174
+ b.call
175
+ rescue Exception => e
176
+ STDERR.puts "WARNING before_thread_start hook failed with exception (#{e.class}) #{e.message}"
177
+ end
178
+ end
179
+ nil
180
+ end
181
+
182
+ private :trigger_before_thread_start_hooks
183
+
184
+ def trigger_before_thread_exit_hooks
185
+ return unless @before_thread_exit&.any?
186
+
187
+ @before_thread_exit.each do |b|
188
+ begin
189
+ b.call
190
+ rescue Exception => e
191
+ STDERR.puts "WARNING before_thread_exit hook failed with exception (#{e.class}) #{e.message}"
192
+ end
193
+ end
194
+ nil
195
+ end
196
+
197
+ private :trigger_before_thread_exit_hooks
198
+
161
199
  # @version 5.0.0
162
200
  def trigger_out_of_band_hook
163
201
  return false unless @out_of_band&.any?
@@ -344,8 +382,8 @@ module Puma
344
382
 
345
383
  # Tell all threads in the pool to exit and wait for them to finish.
346
384
  # Wait +timeout+ seconds then raise +ForceShutdown+ in remaining threads.
347
- # Next, wait an extra +grace+ seconds then force-kill remaining threads.
348
- # Finally, wait +kill_grace+ seconds for remaining threads to exit.
385
+ # Next, wait an extra +@shutdown_grace_time+ seconds then force-kill remaining
386
+ # threads. Finally, wait 1 second for remaining threads to exit.
349
387
  #
350
388
  def shutdown(timeout=-1)
351
389
  threads = with_mutex do
@@ -382,7 +420,7 @@ module Puma
382
420
  t.raise ForceShutdown if t[:with_force_shutdown]
383
421
  end
384
422
  end
385
- join.call(SHUTDOWN_GRACE_TIME)
423
+ join.call(@shutdown_grace_time)
386
424
 
387
425
  # If threads are _still_ running, forcefully kill them and wait to finish.
388
426
  threads.each(&:kill)
data/lib/puma/util.rb CHANGED
File without changes
data/lib/puma.rb CHANGED
File without changes
@@ -1,114 +1,141 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rack/handler'
4
-
5
- module Rack
6
- module Handler
7
- module Puma
8
- DEFAULT_OPTIONS = {
9
- :Verbose => false,
10
- :Silent => false
11
- }
12
-
13
- def self.config(app, options = {})
14
- require_relative '../../puma'
15
- require_relative '../../puma/configuration'
16
- require_relative '../../puma/log_writer'
17
- require_relative '../../puma/launcher'
18
-
19
- default_options = DEFAULT_OPTIONS.dup
20
-
21
- # Libraries pass in values such as :Port and there is no way to determine
22
- # if it is a default provided by the library or a special value provided
23
- # by the user. A special key `user_supplied_options` can be passed. This
24
- # contains an array of all explicitly defined user options. We then
25
- # know that all other values are defaults
26
- if user_supplied_options = options.delete(:user_supplied_options)
27
- (options.keys - user_supplied_options).each do |k|
28
- default_options[k] = options.delete(k)
29
- end
3
+ # This module is used as an 'include' file in code at bottom of file
4
+ module Puma
5
+ module RackHandler
6
+ DEFAULT_OPTIONS = {
7
+ :Verbose => false,
8
+ :Silent => false
9
+ }
10
+
11
+ def config(app, options = {})
12
+ require_relative '../../puma'
13
+ require_relative '../../puma/configuration'
14
+ require_relative '../../puma/log_writer'
15
+ require_relative '../../puma/launcher'
16
+
17
+ default_options = DEFAULT_OPTIONS.dup
18
+
19
+ # Libraries pass in values such as :Port and there is no way to determine
20
+ # if it is a default provided by the library or a special value provided
21
+ # by the user. A special key `user_supplied_options` can be passed. This
22
+ # contains an array of all explicitly defined user options. We then
23
+ # know that all other values are defaults
24
+ if user_supplied_options = options.delete(:user_supplied_options)
25
+ (options.keys - user_supplied_options).each do |k|
26
+ default_options[k] = options.delete(k)
30
27
  end
28
+ end
31
29
 
32
- conf = ::Puma::Configuration.new(options, default_options) do |user_config, file_config, default_config|
33
- if options.delete(:Verbose)
34
- require 'rack/common_logger'
35
- app = Rack::CommonLogger.new(app, STDOUT)
36
- end
30
+ @events = options[:events] || ::Puma::Events.new
37
31
 
38
- if options[:environment]
39
- user_config.environment options[:environment]
32
+ conf = ::Puma::Configuration.new(options, default_options.merge({events: @events})) do |user_config, file_config, default_config|
33
+ if options.delete(:Verbose)
34
+ begin
35
+ require 'rack/commonlogger' # Rack 1.x
36
+ rescue LoadError
37
+ require 'rack/common_logger' # Rack 2 and later
40
38
  end
39
+ app = ::Rack::CommonLogger.new(app, STDOUT)
40
+ end
41
41
 
42
- if options[:Threads]
43
- min, max = options.delete(:Threads).split(':', 2)
44
- user_config.threads min, max
45
- end
42
+ if options[:environment]
43
+ user_config.environment options[:environment]
44
+ end
46
45
 
47
- if options[:Host] || options[:Port]
48
- host = options[:Host] || default_options[:Host]
49
- port = options[:Port] || default_options[:Port]
50
- self.set_host_port_to_config(host, port, user_config)
51
- end
46
+ if options[:Threads]
47
+ min, max = options.delete(:Threads).split(':', 2)
48
+ user_config.threads min, max
49
+ end
52
50
 
53
- if default_options[:Host]
54
- file_config.set_default_host(default_options[:Host])
55
- end
56
- self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
51
+ if options[:Host] || options[:Port]
52
+ host = options[:Host] || default_options[:Host]
53
+ port = options[:Port] || default_options[:Port]
54
+ self.set_host_port_to_config(host, port, user_config)
55
+ end
57
56
 
58
- user_config.app app
57
+ if default_options[:Host]
58
+ file_config.set_default_host(default_options[:Host])
59
59
  end
60
- conf
60
+ self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
61
+
62
+ user_config.app app
61
63
  end
64
+ conf
65
+ end
62
66
 
63
- def self.run(app, **options)
64
- conf = self.config(app, options)
67
+ def run(app, **options)
68
+ conf = self.config(app, options)
65
69
 
66
- log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
70
+ log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
67
71
 
68
- launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer)
72
+ launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer, events: @events)
69
73
 
70
- yield launcher if block_given?
71
- begin
72
- launcher.run
73
- rescue Interrupt
74
- puts "* Gracefully stopping, waiting for requests to finish"
75
- launcher.stop
76
- puts "* Goodbye!"
77
- end
74
+ yield launcher if block_given?
75
+ begin
76
+ launcher.run
77
+ rescue Interrupt
78
+ puts "* Gracefully stopping, waiting for requests to finish"
79
+ launcher.stop
80
+ puts "* Goodbye!"
78
81
  end
82
+ end
79
83
 
80
- def self.valid_options
81
- {
82
- "Host=HOST" => "Hostname to listen on (default: localhost)",
83
- "Port=PORT" => "Port to listen on (default: 8080)",
84
- "Threads=MIN:MAX" => "min:max threads to use (default 0:16)",
85
- "Verbose" => "Don't report each request (default: false)"
86
- }
87
- end
84
+ def valid_options
85
+ {
86
+ "Host=HOST" => "Hostname to listen on (default: localhost)",
87
+ "Port=PORT" => "Port to listen on (default: 8080)",
88
+ "Threads=MIN:MAX" => "min:max threads to use (default 0:16)",
89
+ "Verbose" => "Don't report each request (default: false)"
90
+ }
91
+ end
88
92
 
89
- def self.set_host_port_to_config(host, port, config)
90
- config.clear_binds! if host || port
93
+ def set_host_port_to_config(host, port, config)
94
+ config.clear_binds! if host || port
91
95
 
92
- if host && (host[0,1] == '.' || host[0,1] == '/')
93
- config.bind "unix://#{host}"
94
- elsif host && host =~ /^ssl:\/\//
95
- uri = URI.parse(host)
96
- uri.port ||= port || ::Puma::Configuration::DEFAULTS[:tcp_port]
97
- config.bind uri.to_s
98
- else
96
+ if host && (host[0,1] == '.' || host[0,1] == '/')
97
+ config.bind "unix://#{host}"
98
+ elsif host && host =~ /^ssl:\/\//
99
+ uri = URI.parse(host)
100
+ uri.port ||= port || ::Puma::Configuration::DEFAULTS[:tcp_port]
101
+ config.bind uri.to_s
102
+ else
99
103
 
100
- if host
101
- port ||= ::Puma::Configuration::DEFAULTS[:tcp_port]
102
- end
104
+ if host
105
+ port ||= ::Puma::Configuration::DEFAULTS[:tcp_port]
106
+ end
103
107
 
104
- if port
105
- host ||= ::Puma::Configuration::DEFAULTS[:tcp_host]
106
- config.port port, host
107
- end
108
+ if port
109
+ host ||= ::Puma::Configuration::DEFAULTS[:tcp_host]
110
+ config.port port, host
108
111
  end
109
112
  end
110
113
  end
114
+ end
115
+ end
111
116
 
112
- register :puma, Puma
117
+ # rackup was removed in Rack 3, it is now a separate gem
118
+ if Object.const_defined? :Rackup
119
+ module Rackup
120
+ module Handler
121
+ module Puma
122
+ class << self
123
+ include ::Puma::RackHandler
124
+ end
125
+ end
126
+ register :puma, Puma
127
+ end
128
+ end
129
+ else
130
+ do_register = Object.const_defined?(:Rack) && Rack.release < '3'
131
+ module Rack
132
+ module Handler
133
+ module Puma
134
+ class << self
135
+ include ::Puma::RackHandler
136
+ end
137
+ end
138
+ end
113
139
  end
140
+ ::Rack::Handler.register(:puma, ::Rack::Handler::Puma) if do_register
114
141
  end
data/tools/Dockerfile CHANGED
@@ -1,6 +1,6 @@
1
1
  # Use this Dockerfile to create minimal reproductions of issues
2
2
 
3
- FROM ruby:3.1
3
+ FROM ruby:3.2
4
4
 
5
5
  # throw errors if Gemfile has been modified since Gemfile.lock
6
6
  RUN bundle config --global frozen 1
@@ -8,7 +8,7 @@ RUN bundle config --global frozen 1
8
8
  WORKDIR /usr/src/app
9
9
 
10
10
  COPY . .
11
- RUN gem install bundler
11
+
12
12
  RUN bundle install
13
13
  RUN bundle exec rake compile
14
14
 
data/tools/trickletest.rb CHANGED
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.2
4
+ version: 6.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Phoenix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 1980-01-01 00:00:00.000000000 Z
11
+ date: 2024-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r
@@ -104,6 +104,7 @@ files:
104
104
  - lib/puma/minissl/context_builder.rb
105
105
  - lib/puma/null_io.rb
106
106
  - lib/puma/plugin.rb
107
+ - lib/puma/plugin/systemd.rb
107
108
  - lib/puma/plugin/tmp_restart.rb
108
109
  - lib/puma/rack/builder.rb
109
110
  - lib/puma/rack/urlmap.rb
@@ -111,10 +112,10 @@ files:
111
112
  - lib/puma/reactor.rb
112
113
  - lib/puma/request.rb
113
114
  - lib/puma/runner.rb
115
+ - lib/puma/sd_notify.rb
114
116
  - lib/puma/server.rb
115
117
  - lib/puma/single.rb
116
118
  - lib/puma/state_file.rb
117
- - lib/puma/systemd.rb
118
119
  - lib/puma/thread_pool.rb
119
120
  - lib/puma/util.rb
120
121
  - lib/rack/handler/puma.rb
@@ -144,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
145
  - !ruby/object:Gem::Version
145
146
  version: '0'
146
147
  requirements: []
147
- rubygems_version: 3.2.26
148
+ rubygems_version: 3.5.3
148
149
  signing_key:
149
150
  specification_version: 4
150
151
  summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for