puma 6.0.0 → 6.6.0

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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +392 -13
  3. data/LICENSE +0 -0
  4. data/README.md +135 -29
  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 +11 -1
  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/java_options.md +54 -0
  14. data/docs/jungle/README.md +0 -0
  15. data/docs/jungle/rc.d/README.md +0 -0
  16. data/docs/jungle/rc.d/puma.conf +0 -0
  17. data/docs/kubernetes.md +12 -0
  18. data/docs/nginx.md +1 -1
  19. data/docs/plugins.md +4 -0
  20. data/docs/rails_dev_mode.md +0 -0
  21. data/docs/restart.md +1 -0
  22. data/docs/signals.md +2 -2
  23. data/docs/stats.md +8 -3
  24. data/docs/systemd.md +13 -7
  25. data/docs/testing_benchmarks_local_files.md +0 -0
  26. data/docs/testing_test_rackup_ci_files.md +0 -0
  27. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  28. data/ext/puma_http11/ext_help.h +0 -0
  29. data/ext/puma_http11/extconf.rb +21 -14
  30. data/ext/puma_http11/http11_parser.c +0 -0
  31. data/ext/puma_http11/http11_parser.h +0 -0
  32. data/ext/puma_http11/http11_parser.java.rl +0 -0
  33. data/ext/puma_http11/http11_parser.rl +0 -0
  34. data/ext/puma_http11/http11_parser_common.rl +0 -0
  35. data/ext/puma_http11/mini_ssl.c +107 -10
  36. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  37. data/ext/puma_http11/org/jruby/puma/Http11.java +30 -7
  38. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +0 -0
  39. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +2 -1
  40. data/ext/puma_http11/puma_http11.c +4 -1
  41. data/lib/puma/app/status.rb +1 -1
  42. data/lib/puma/binder.rb +26 -15
  43. data/lib/puma/cli.rb +13 -5
  44. data/lib/puma/client.rb +113 -26
  45. data/lib/puma/cluster/worker.rb +14 -6
  46. data/lib/puma/cluster/worker_handle.rb +4 -5
  47. data/lib/puma/cluster.rb +93 -22
  48. data/lib/puma/commonlogger.rb +21 -14
  49. data/lib/puma/configuration.rb +42 -22
  50. data/lib/puma/const.rb +149 -89
  51. data/lib/puma/control_cli.rb +16 -9
  52. data/lib/puma/detect.rb +5 -4
  53. data/lib/puma/dsl.rb +432 -40
  54. data/lib/puma/error_logger.rb +6 -5
  55. data/lib/puma/events.rb +0 -0
  56. data/lib/puma/io_buffer.rb +10 -0
  57. data/lib/puma/jruby_restart.rb +0 -16
  58. data/lib/puma/json_serialization.rb +0 -0
  59. data/lib/puma/launcher/bundle_pruner.rb +0 -0
  60. data/lib/puma/launcher.rb +29 -29
  61. data/lib/puma/log_writer.rb +23 -13
  62. data/lib/puma/minissl/context_builder.rb +4 -0
  63. data/lib/puma/minissl.rb +23 -0
  64. data/lib/puma/null_io.rb +42 -2
  65. data/lib/puma/plugin/systemd.rb +90 -0
  66. data/lib/puma/plugin/tmp_restart.rb +0 -0
  67. data/lib/puma/plugin.rb +0 -0
  68. data/lib/puma/rack/builder.rb +2 -2
  69. data/lib/puma/rack/urlmap.rb +1 -1
  70. data/lib/puma/rack_default.rb +18 -3
  71. data/lib/puma/reactor.rb +17 -8
  72. data/lib/puma/request.rb +207 -126
  73. data/lib/puma/runner.rb +26 -4
  74. data/lib/puma/sd_notify.rb +146 -0
  75. data/lib/puma/server.rb +121 -49
  76. data/lib/puma/single.rb +3 -1
  77. data/lib/puma/state_file.rb +2 -2
  78. data/lib/puma/thread_pool.rb +56 -9
  79. data/lib/puma/util.rb +1 -1
  80. data/lib/puma.rb +1 -3
  81. data/lib/rack/handler/puma.rb +116 -86
  82. data/tools/Dockerfile +2 -2
  83. data/tools/trickletest.rb +0 -0
  84. metadata +12 -13
  85. data/lib/puma/systemd.rb +0 -47
data/lib/puma/dsl.rb CHANGED
@@ -47,11 +47,13 @@ module Puma
47
47
  # | on_worker_boot | :before_worker_boot | inside, before |
48
48
  # | on_worker_shutdown | :before_worker_shutdown | inside, after |
49
49
  # | on_refork | :before_refork | inside |
50
+ # | after_refork | :after_refork | inside |
50
51
  #
51
52
  class DSL
52
53
  ON_WORKER_KEY = [String, Symbol].freeze
53
54
 
54
- # convenience method so logic can be used in CI
55
+ # Convenience method so logic can be used in CI.
56
+ #
55
57
  # @see ssl_bind
56
58
  #
57
59
  def self.ssl_bind_str(host, port, opts)
@@ -65,6 +67,7 @@ module Puma
65
67
 
66
68
  ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
67
69
 
70
+ low_latency_str = opts.key?(:low_latency) ? "&low_latency=#{opts[:low_latency]}" : ''
68
71
  backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
69
72
 
70
73
  if defined?(JRUBY_VERSION)
@@ -84,10 +87,12 @@ module Puma
84
87
  "&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
85
88
  else
86
89
  ssl_cipher_filter = opts[:ssl_cipher_filter] ? "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
90
+ ssl_ciphersuites = opts[:ssl_ciphersuites] ? "&ssl_ciphersuites=#{opts[:ssl_ciphersuites]}" : nil
87
91
  v_flags = (ary = opts[:verification_flags]) ? "&verification_flags=#{Array(ary).join ','}" : nil
88
92
 
89
93
  cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(cert)}" : nil
90
94
  key_flags = (key = opts[:key]) ? "&key=#{Puma::Util.escape(key)}" : nil
95
+ password_flags = (password_command = opts[:key_password_command]) ? "&key_password_command=#{Puma::Util.escape(password_command)}" : nil
91
96
 
92
97
  reuse_flag =
93
98
  if (reuse = opts[:reuse])
@@ -113,8 +118,8 @@ module Puma
113
118
  nil
114
119
  end
115
120
 
116
- "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{ssl_cipher_filter}" \
117
- "#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
121
+ "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{password_flags}#{ssl_cipher_filter}#{ssl_ciphersuites}" \
122
+ "#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}#{low_latency_str}"
118
123
  end
119
124
  end
120
125
 
@@ -161,7 +166,10 @@ module Puma
161
166
  @options[key.to_sym] || default
162
167
  end
163
168
 
164
- # Load the named plugin for use by this configuration
169
+ # Load the named plugin for use by this configuration.
170
+ #
171
+ # @example
172
+ # plugin :tmp_restart
165
173
  #
166
174
  def plugin(name)
167
175
  @plugins << @config.load_plugin(name)
@@ -208,6 +216,7 @@ module Puma
208
216
  # activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
209
217
  # @example
210
218
  # activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
219
+ #
211
220
  def activate_control_app(url="auto", opts={})
212
221
  if url == "auto"
213
222
  path = Configuration.temp_path
@@ -233,8 +242,12 @@ module Puma
233
242
  @options[:control_url_umask] = opts[:umask] if opts[:umask]
234
243
  end
235
244
 
236
- # Load additional configuration from a file
237
- # Files get loaded later via Configuration#load
245
+ # Load additional configuration from a file.
246
+ # Files get loaded later via Configuration#load.
247
+ #
248
+ # @example
249
+ # load 'config/puma/production.rb'
250
+ #
238
251
  def load(file)
239
252
  @options[:config_files] ||= []
240
253
  @options[:config_files] << file
@@ -250,6 +263,7 @@ module Puma
250
263
  #
251
264
  # * Set the socket backlog depth with +backlog+, default is 1024.
252
265
  # * Set up an SSL certificate with +key+ & +cert+.
266
+ # * Set up an SSL certificate for mTLS with +key+, +cert+, +ca+ and +verify_mode+.
253
267
  # * Set whether to optimize for low latency instead of throughput with
254
268
  # +low_latency+, default is to not optimize for low latency. This is done
255
269
  # via +Socket::TCP_NODELAY+.
@@ -259,10 +273,13 @@ module Puma
259
273
  # bind 'unix:///var/run/puma.sock?backlog=512'
260
274
  # @example SSL cert
261
275
  # bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
276
+ # @example SSL cert for mutual TLS (mTLS)
277
+ # bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem&ca=ca.pem&verify_mode=force_peer'
262
278
  # @example Disable optimization for low latency
263
279
  # bind 'tcp://0.0.0.0:9292?low_latency=false'
264
280
  # @example Socket permissions
265
281
  # bind 'unix:///var/run/puma.sock?umask=0111'
282
+ #
266
283
  # @see Puma::Runner#load_and_bind
267
284
  # @see Puma::Cluster#run
268
285
  #
@@ -297,33 +314,70 @@ module Puma
297
314
  #
298
315
  # @example Only bind to systemd activated sockets, ignoring other binds
299
316
  # bind_to_activated_sockets 'only'
317
+ #
300
318
  def bind_to_activated_sockets(bind=true)
301
319
  @options[:bind_to_activated_sockets] = bind
302
320
  end
303
321
 
304
- # Define the TCP port to bind to. Use +bind+ for more advanced options.
322
+ # Define the TCP port to bind to. Use `bind` for more advanced options.
323
+ #
324
+ # The default is +9292+.
305
325
  #
306
326
  # @example
307
- # port 9292
327
+ # port 3000
328
+ #
308
329
  def port(port, host=nil)
309
330
  host ||= default_host
310
331
  bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
311
332
  end
312
333
 
334
+ # Define how long the tcp socket stays open, if no data has been received.
335
+ #
336
+ # The default is 30 seconds.
337
+ #
338
+ # @example
339
+ # first_data_timeout 40
340
+ #
341
+ # @see Puma::Server.new
342
+ #
343
+ def first_data_timeout(seconds)
344
+ @options[:first_data_timeout] = Integer(seconds)
345
+ end
346
+
313
347
  # Define how long persistent connections can be idle before Puma closes them.
348
+ #
349
+ # The default is 20 seconds.
350
+ #
351
+ # @example
352
+ # persistent_timeout 30
353
+ #
314
354
  # @see Puma::Server.new
355
+ #
315
356
  def persistent_timeout(seconds)
316
357
  @options[:persistent_timeout] = Integer(seconds)
317
358
  end
318
359
 
319
- # Define how long the tcp socket stays open, if no data has been received.
360
+ # If a new request is not received within this number of seconds, begin shutting down.
361
+ #
362
+ # The default is +nil+.
363
+ #
364
+ # @example
365
+ # idle_timeout 60
366
+ #
320
367
  # @see Puma::Server.new
321
- def first_data_timeout(seconds)
322
- @options[:first_data_timeout] = Integer(seconds)
368
+ #
369
+ def idle_timeout(seconds)
370
+ @options[:idle_timeout] = Integer(seconds)
323
371
  end
324
372
 
325
373
  # Work around leaky apps that leave garbage in Thread locals
326
374
  # across requests.
375
+ #
376
+ # The default is +false+.
377
+ #
378
+ # @example
379
+ # clean_thread_locals
380
+ #
327
381
  def clean_thread_locals(which=true)
328
382
  @options[:clean_thread_locals] = which
329
383
  end
@@ -331,6 +385,7 @@ module Puma
331
385
  # When shutting down, drain the accept socket of pending connections and
332
386
  # process them. This loops over the accept socket until there are no more
333
387
  # read events and then stops looking and waits for the requests to finish.
388
+ #
334
389
  # @see Puma::Server#graceful_shutdown
335
390
  #
336
391
  def drain_on_shutdown(which=true)
@@ -344,18 +399,22 @@ module Puma
344
399
  #
345
400
  # @example
346
401
  # environment 'production'
402
+ #
347
403
  def environment(environment)
348
404
  @options[:environment] = environment
349
405
  end
350
406
 
351
- # How long to wait for threads to stop when shutting them
352
- # down. Defaults to :forever. Specifying :immediately will cause
353
- # Puma to kill the threads immediately. Otherwise the value
354
- # is the number of seconds to wait.
407
+ # How long to wait for threads to stop when shutting them down.
408
+ # Specifying :immediately will cause Puma to kill the threads immediately.
409
+ # Otherwise the value is the number of seconds to wait.
355
410
  #
356
411
  # Puma always waits a few seconds after killing a thread for it to try
357
412
  # to finish up it's work, even in :immediately mode.
413
+ #
414
+ # The default is +:forever+.
415
+ #
358
416
  # @see Puma::Server#graceful_shutdown
417
+ #
359
418
  def force_shutdown_after(val=:forever)
360
419
  i = case val
361
420
  when :forever
@@ -378,9 +437,9 @@ module Puma
378
437
  # on_restart do
379
438
  # puts 'On restart...'
380
439
  # end
440
+ #
381
441
  def on_restart(&block)
382
- @options[:on_restart] ||= []
383
- @options[:on_restart] << block
442
+ process_hook :on_restart, nil, block, 'on_restart'
384
443
  end
385
444
 
386
445
  # Command to use to restart Puma. This should be just how to
@@ -389,6 +448,7 @@ module Puma
389
448
  #
390
449
  # @example
391
450
  # restart_command '/u/app/lolcat/bin/restart_puma'
451
+ #
392
452
  def restart_command(cmd)
393
453
  @options[:restart_cmd] = cmd.to_s
394
454
  end
@@ -397,26 +457,49 @@ module Puma
397
457
  #
398
458
  # @example
399
459
  # pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
460
+ #
400
461
  def pidfile(path)
401
462
  @options[:pidfile] = path.to_s
402
463
  end
403
464
 
404
- # Disable request logging, if this isn't used it'll be enabled by default.
465
+ # Disable request logging, the inverse of `log_requests`.
466
+ #
467
+ # The default is +true+.
405
468
  #
406
469
  # @example
407
470
  # quiet
471
+ #
408
472
  def quiet(which=true)
409
473
  @options[:log_requests] = !which
410
474
  end
411
475
 
412
- # Enable request logging
476
+ # Enable request logging, the inverse of `quiet`.
477
+ #
478
+ # The default is +false+.
479
+ #
480
+ # @example
481
+ # log_requests
413
482
  #
414
483
  def log_requests(which=true)
415
484
  @options[:log_requests] = which
416
485
  end
417
486
 
487
+ # Pass in a custom logging class instance
488
+ #
489
+ # @example
490
+ # custom_logger Logger.new('t.log')
491
+ #
492
+ def custom_logger(custom_logger)
493
+ @options[:custom_logger] = custom_logger
494
+ end
495
+
418
496
  # Show debugging info
419
497
  #
498
+ # The default is +false+.
499
+ #
500
+ # @example
501
+ # debug
502
+ #
420
503
  def debug
421
504
  @options[:debug] = true
422
505
  end
@@ -427,6 +510,7 @@ module Puma
427
510
  #
428
511
  # @example
429
512
  # rackup '/u/apps/lolcat/config.ru'
513
+ #
430
514
  def rackup(path)
431
515
  @options[:rackup] ||= path.to_s
432
516
  end
@@ -434,21 +518,32 @@ module Puma
434
518
  # Allows setting `env['rack.url_scheme']`.
435
519
  # Only necessary if X-Forwarded-Proto is not being set by your proxy
436
520
  # Normal values are 'http' or 'https'.
521
+ #
437
522
  def rack_url_scheme(scheme=nil)
438
523
  @options[:rack_url_scheme] = scheme
439
524
  end
440
525
 
526
+ # Enable HTTP 103 Early Hints responses.
527
+ #
528
+ # The default is +nil+.
529
+ #
530
+ # @example
531
+ # early_hints
532
+ #
441
533
  def early_hints(answer=true)
442
534
  @options[:early_hints] = answer
443
535
  end
444
536
 
445
537
  # Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
446
- # specifies whether the output is appended, the default is +false+.
538
+ # specifies whether the output is appended.
539
+ #
540
+ # The default is +false+.
447
541
  #
448
542
  # @example
449
543
  # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
450
544
  # @example
451
545
  # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
546
+ #
452
547
  def stdout_redirect(stdout=nil, stderr=nil, append=false)
453
548
  @options[:redirect_stdout] = stdout
454
549
  @options[:redirect_stderr] = stderr
@@ -459,8 +554,9 @@ module Puma
459
554
  @options[:log_formatter] = block
460
555
  end
461
556
 
462
- # Configure +min+ to be the minimum number of threads to use to answer
463
- # requests and +max+ the maximum.
557
+ # Configure the number of threads to use to answer requests.
558
+ #
559
+ # It can be a single fixed number, or a +min+ and a +max+.
464
560
  #
465
561
  # The default is the environment variables +PUMA_MIN_THREADS+ / +PUMA_MAX_THREADS+
466
562
  # (or +MIN_THREADS+ / +MAX_THREADS+ if the +PUMA_+ variables aren't set).
@@ -468,10 +564,13 @@ module Puma
468
564
  # If these environment variables aren't set, the default is "0, 5" in MRI or "0, 16" for other interpreters.
469
565
  #
470
566
  # @example
567
+ # threads 5
568
+ # @example
471
569
  # threads 0, 16
472
570
  # @example
473
571
  # threads 5, 5
474
- def threads(min, max)
572
+ #
573
+ def threads(min, max = min)
475
574
  min = Integer(min)
476
575
  max = Integer(max)
477
576
  if min > max
@@ -500,11 +599,18 @@ module Puma
500
599
  # `true`, which sets reuse 'on' with default values, or a hash, with `:size`
501
600
  # and/or `:timeout` keys, each with integer values.
502
601
  #
602
+ # The `cert:` options hash parameter can be the path to a certificate
603
+ # file including all intermediate certificates in PEM format.
604
+ #
605
+ # The `cert_pem:` options hash parameter can be String containing the
606
+ # cerificate and all intermediate certificates in PEM format.
607
+ #
503
608
  # @example
504
609
  # ssl_bind '127.0.0.1', '9292', {
505
610
  # cert: path_to_cert,
506
611
  # key: path_to_key,
507
612
  # ssl_cipher_filter: cipher_filter, # optional
613
+ # ssl_ciphersuites: ciphersuites, # optional
508
614
  # verify_mode: verify_mode, # default 'none'
509
615
  # verification_flags: flags, # optional, not supported by JRuby
510
616
  # reuse: true # optional
@@ -527,6 +633,7 @@ module Puma
527
633
  # ssl_cipher_list: cipher_list, # optional
528
634
  # verify_mode: verify_mode # default 'none'
529
635
  # }
636
+ #
530
637
  def ssl_bind(host, port, opts = {})
531
638
  add_pem_values_to_options_store(opts)
532
639
  bind self.class.ssl_bind_str(host, port, opts)
@@ -537,6 +644,7 @@ module Puma
537
644
  #
538
645
  # @example
539
646
  # state_path '/u/apps/lolcat/tmp/pids/puma.state'
647
+ #
540
648
  def state_path(path)
541
649
  @options[:state] = path.to_s
542
650
  end
@@ -545,6 +653,7 @@ module Puma
545
653
  #
546
654
  # @example
547
655
  # state_permission 0600
656
+ #
548
657
  # @version 5.0.0
549
658
  #
550
659
  def state_permission(permission)
@@ -558,7 +667,12 @@ module Puma
558
667
  # set, otherwise 0.
559
668
  #
560
669
  # @note Cluster mode only.
670
+ #
671
+ # @example
672
+ # workers 2
673
+ #
561
674
  # @see Puma::Cluster
675
+ #
562
676
  def workers(count)
563
677
  @options[:workers] = count.to_i
564
678
  end
@@ -576,11 +690,28 @@ module Puma
576
690
  #
577
691
  # Moving from workers = 1 to workers = 0 will save 10-30% of memory use.
578
692
  #
693
+ # The default is +false+.
694
+ #
579
695
  # @note Cluster mode only.
696
+ #
697
+ # @example
698
+ # silence_single_worker_warning
699
+ #
580
700
  def silence_single_worker_warning
581
701
  @options[:silence_single_worker_warning] = true
582
702
  end
583
703
 
704
+ # Disable warning message when running single mode with callback hook defined.
705
+ #
706
+ # The default is +false+.
707
+ #
708
+ # @example
709
+ # silence_fork_callback_warning
710
+ #
711
+ def silence_fork_callback_warning
712
+ @options[:silence_fork_callback_warning] = true
713
+ end
714
+
584
715
  # Code to run immediately before master process
585
716
  # forks workers (once on boot). These hooks can block if necessary
586
717
  # to wait for background operations unknown to Puma to finish before
@@ -591,13 +722,16 @@ module Puma
591
722
  # This can be called multiple times to add several hooks.
592
723
  #
593
724
  # @note Cluster mode only.
725
+ #
594
726
  # @example
595
727
  # before_fork do
596
728
  # puts "Starting workers..."
597
729
  # end
730
+ #
598
731
  def before_fork(&block)
599
- @options[:before_fork] ||= []
600
- @options[:before_fork] << block
732
+ warn_if_in_single_mode('before_fork')
733
+
734
+ process_hook :before_fork, nil, block, 'before_fork'
601
735
  end
602
736
 
603
737
  # Code to run in a worker when it boots to setup
@@ -606,27 +740,36 @@ module Puma
606
740
  # This can be called multiple times to add several hooks.
607
741
  #
608
742
  # @note Cluster mode only.
743
+ #
609
744
  # @example
610
745
  # on_worker_boot do
611
746
  # puts 'Before worker boot...'
612
747
  # end
748
+ #
613
749
  def on_worker_boot(key = nil, &block)
750
+ warn_if_in_single_mode('on_worker_boot')
751
+
614
752
  process_hook :before_worker_boot, key, block, 'on_worker_boot'
615
753
  end
616
754
 
617
755
  # Code to run immediately before a worker shuts
618
- # down (after it has finished processing HTTP requests). These hooks
756
+ # down (after it has finished processing HTTP requests). The worker's
757
+ # index is passed as an argument. These hooks
619
758
  # can block if necessary to wait for background operations unknown
620
759
  # to Puma to finish before the process terminates.
621
760
  #
622
761
  # This can be called multiple times to add several hooks.
623
762
  #
624
763
  # @note Cluster mode only.
764
+ #
625
765
  # @example
626
766
  # on_worker_shutdown do
627
767
  # puts 'On worker shutdown...'
628
768
  # end
769
+ #
629
770
  def on_worker_shutdown(key = nil, &block)
771
+ warn_if_in_single_mode('on_worker_shutdown')
772
+
630
773
  process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
631
774
  end
632
775
 
@@ -636,11 +779,15 @@ module Puma
636
779
  # This can be called multiple times to add several hooks.
637
780
  #
638
781
  # @note Cluster mode only.
782
+ #
639
783
  # @example
640
784
  # on_worker_fork do
641
785
  # puts 'Before worker fork...'
642
786
  # end
787
+ #
643
788
  def on_worker_fork(&block)
789
+ warn_if_in_single_mode('on_worker_fork')
790
+
644
791
  process_hook :before_worker_fork, nil, block, 'on_worker_fork'
645
792
  end
646
793
 
@@ -650,16 +797,42 @@ module Puma
650
797
  # This is called everytime a worker is to be started.
651
798
  #
652
799
  # @note Cluster mode only.
800
+ #
653
801
  # @example
654
802
  # after_worker_fork do
655
803
  # puts 'After worker fork...'
656
804
  # end
805
+ #
657
806
  def after_worker_fork(&block)
807
+ warn_if_in_single_mode('after_worker_fork')
808
+
658
809
  process_hook :after_worker_fork, nil, block, 'after_worker_fork'
659
810
  end
660
811
 
661
812
  alias_method :after_worker_boot, :after_worker_fork
662
813
 
814
+ # Code to run after puma is booted (works for both: single and clustered)
815
+ #
816
+ # @example
817
+ # on_booted do
818
+ # puts 'After booting...'
819
+ # end
820
+ #
821
+ def on_booted(&block)
822
+ @config.options[:events].on_booted(&block)
823
+ end
824
+
825
+ # Code to run after puma is stopped (works for both: single and clustered)
826
+ #
827
+ # @example
828
+ # on_stopped do
829
+ # puts 'After stopping...'
830
+ # end
831
+ #
832
+ def on_stopped(&block)
833
+ @config.options[:events].on_stopped(&block)
834
+ end
835
+
663
836
  # When `fork_worker` is enabled, code to run in Worker 0
664
837
  # before all other workers are re-forked from this process,
665
838
  # after the server has temporarily stopped serving requests
@@ -672,16 +845,86 @@ module Puma
672
845
  # This can be called multiple times to add several hooks.
673
846
  #
674
847
  # @note Cluster mode with `fork_worker` enabled only.
848
+ #
675
849
  # @example
676
850
  # on_refork do
677
851
  # 3.times {GC.start}
678
852
  # end
853
+ #
679
854
  # @version 5.0.0
680
855
  #
681
856
  def on_refork(key = nil, &block)
857
+ warn_if_in_single_mode('on_refork')
858
+
682
859
  process_hook :before_refork, key, block, 'on_refork'
683
860
  end
684
861
 
862
+ # When `fork_worker` is enabled, code to run in Worker 0
863
+ # after all other workers are re-forked from this process,
864
+ # after the server has temporarily stopped serving requests
865
+ # (once per complete refork cycle).
866
+ #
867
+ # This can be used to re-open any connections to remote servers
868
+ # (database, Redis, ...) that were closed via on_refork.
869
+ #
870
+ # This can be called multiple times to add several hooks.
871
+ #
872
+ # @note Cluster mode with `fork_worker` enabled only.
873
+ #
874
+ # @example
875
+ # after_refork do
876
+ # puts 'After refork...'
877
+ # end
878
+ #
879
+ def after_refork(key = nil, &block)
880
+ process_hook :after_refork, key, block, 'after_refork'
881
+ end
882
+
883
+ # Provide a block to be executed just before a thread is added to the thread
884
+ # pool. Be careful: while the block executes, thread creation is delayed, and
885
+ # probably a request will have to wait too! The new thread will not be added to
886
+ # the threadpool until the provided block returns.
887
+ #
888
+ # Return values are ignored.
889
+ # Raising an exception will log a warning.
890
+ #
891
+ # This hook is useful for doing something when the thread pool grows.
892
+ #
893
+ # This can be called multiple times to add several hooks.
894
+ #
895
+ # @example
896
+ # on_thread_start do
897
+ # puts 'On thread start...'
898
+ # end
899
+ #
900
+ def on_thread_start(&block)
901
+ process_hook :before_thread_start, nil, block, 'on_thread_start'
902
+ end
903
+
904
+ # Provide a block to be executed after a thread is trimmed from the thread
905
+ # pool. Be careful: while this block executes, Puma's main loop is
906
+ # blocked, so no new requests will be picked up.
907
+ #
908
+ # This hook only runs when a thread in the threadpool is trimmed by Puma.
909
+ # It does not run when a thread dies due to exceptions or any other cause.
910
+ #
911
+ # Return values are ignored.
912
+ # Raising an exception will log a warning.
913
+ #
914
+ # This hook is useful for cleaning up thread local resources when a thread
915
+ # is trimmed.
916
+ #
917
+ # This can be called multiple times to add several hooks.
918
+ #
919
+ # @example
920
+ # on_thread_exit do
921
+ # puts 'On thread exit...'
922
+ # end
923
+ #
924
+ def on_thread_exit(&block)
925
+ process_hook :before_thread_exit, nil, block, 'on_thread_exit'
926
+ end
927
+
685
928
  # Code to run out-of-band when the worker is idle.
686
929
  # These hooks run immediately after a request has finished
687
930
  # processing and there are no busy threads on the worker.
@@ -691,6 +934,7 @@ module Puma
691
934
  # or scheduling asynchronous tasks to execute after a response.
692
935
  #
693
936
  # This can be called multiple times to add several hooks.
937
+ #
694
938
  def out_of_band(&block)
695
939
  process_hook :out_of_band, nil, block, 'out_of_band'
696
940
  end
@@ -701,16 +945,21 @@ module Puma
701
945
  #
702
946
  # @example
703
947
  # directory '/u/apps/lolcat'
948
+ #
704
949
  def directory(dir)
705
950
  @options[:directory] = dir.to_s
706
951
  end
707
952
 
708
953
  # Preload the application before starting the workers; this conflicts with
709
- # phased restart feature. On by default if your app uses more than 1 worker.
954
+ # phased restart feature.
955
+ #
956
+ # The default is +true+ if your app uses more than 1 worker.
710
957
  #
711
958
  # @note Cluster mode only.
959
+ #
712
960
  # @example
713
961
  # preload_app!
962
+ #
714
963
  def preload_app!(answer=true)
715
964
  @options[:preload_app] = answer
716
965
  end
@@ -722,6 +971,7 @@ module Puma
722
971
  # lowlevel_error_handler do |err|
723
972
  # [200, {}, ["error page"]]
724
973
  # end
974
+ #
725
975
  def lowlevel_error_handler(obj=nil, &block)
726
976
  obj ||= block
727
977
  raise "Provide either a #call'able or a block" unless obj
@@ -741,23 +991,26 @@ module Puma
741
991
  # new Bundler context and thus can float around as the release
742
992
  # dictates.
743
993
  #
744
- # @see extra_runtime_dependencies
745
- #
746
994
  # @note This is incompatible with +preload_app!+.
747
995
  # @note This is only supported for RubyGems 2.2+
996
+ #
997
+ # @see extra_runtime_dependencies
998
+ #
748
999
  def prune_bundler(answer=true)
749
1000
  @options[:prune_bundler] = answer
750
1001
  end
751
1002
 
752
- # By default, Puma will raise SignalException when SIGTERM is received. In
753
- # environments where SIGTERM is something expected, you can suppress these
754
- # with this option.
1003
+ # Raises a SignalException when SIGTERM is received. In environments where
1004
+ # SIGTERM is something expected, you can suppress these with this option.
755
1005
  #
756
1006
  # This can be useful for example in Kubernetes, where rolling restart is
757
- # guaranteed usually on infrastructure level.
1007
+ # guaranteed usually on the infrastructure level.
1008
+ #
1009
+ # The default is +true+.
758
1010
  #
759
1011
  # @example
760
1012
  # raise_exception_on_sigterm false
1013
+ #
761
1014
  # @see Puma::Launcher#setup_signals
762
1015
  # @see Puma::Cluster#setup_signals
763
1016
  #
@@ -776,6 +1029,7 @@ module Puma
776
1029
  # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
777
1030
  # @example
778
1031
  # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
1032
+ #
779
1033
  # @see Puma::Launcher#extra_runtime_deps_directories
780
1034
  #
781
1035
  def extra_runtime_dependencies(answer = [])
@@ -787,21 +1041,26 @@ module Puma
787
1041
  # If you do not specify a tag, Puma will infer it. If you do not want Puma
788
1042
  # to add a tag, use an empty string.
789
1043
  #
1044
+ # The default is the current file or directory base name.
1045
+ #
790
1046
  # @example
791
1047
  # tag 'app name'
792
1048
  # @example
793
1049
  # tag ''
1050
+ #
794
1051
  def tag(string)
795
1052
  @options[:tag] = string.to_s
796
1053
  end
797
1054
 
798
1055
  # Change the default interval for checking workers.
799
1056
  #
800
- # The default value is 5 seconds.
1057
+ # The default is 5 seconds.
801
1058
  #
802
1059
  # @note Cluster mode only.
1060
+ #
803
1061
  # @example
804
- # worker_check_interval 5
1062
+ # worker_check_interval 10
1063
+ #
805
1064
  # @see Puma::Cluster#check_workers
806
1065
  #
807
1066
  def worker_check_interval(interval)
@@ -813,11 +1072,15 @@ module Puma
813
1072
  # not a request timeout, it is to protect against a hung or dead process.
814
1073
  # Setting this value will not protect against slow requests.
815
1074
  #
816
- # The minimum value is 6 seconds, the default value is 60 seconds.
1075
+ # This value must be greater than worker_check_interval.
1076
+ #
1077
+ # The default is 60 seconds.
817
1078
  #
818
1079
  # @note Cluster mode only.
1080
+ #
819
1081
  # @example
820
1082
  # worker_timeout 60
1083
+ #
821
1084
  # @see Puma::Cluster::Worker#ping_timeout
822
1085
  #
823
1086
  def worker_timeout(timeout)
@@ -833,12 +1096,13 @@ module Puma
833
1096
 
834
1097
  # Change the default worker timeout for booting.
835
1098
  #
836
- # If unspecified, this defaults to the value of worker_timeout.
1099
+ # The default is the value of `worker_timeout`.
837
1100
  #
838
1101
  # @note Cluster mode only.
839
1102
  #
840
1103
  # @example
841
1104
  # worker_boot_timeout 60
1105
+ #
842
1106
  # @see Puma::Cluster::Worker#ping_timeout
843
1107
  #
844
1108
  def worker_boot_timeout(timeout)
@@ -847,7 +1111,13 @@ module Puma
847
1111
 
848
1112
  # Set the timeout for worker shutdown.
849
1113
  #
1114
+ # The default is 60 seconds.
1115
+ #
850
1116
  # @note Cluster mode only.
1117
+ #
1118
+ # @example
1119
+ # worker_shutdown_timeout 90
1120
+ #
851
1121
  # @see Puma::Cluster::Worker#term
852
1122
  #
853
1123
  def worker_shutdown_timeout(timeout)
@@ -863,9 +1133,13 @@ module Puma
863
1133
  # 2. **:oldest** - the oldest workers (i.e. the workers that were started
864
1134
  # the longest time ago) will be culled.
865
1135
  #
1136
+ # The default is +:youngest+.
1137
+ #
866
1138
  # @note Cluster mode only.
1139
+ #
867
1140
  # @example
868
1141
  # worker_culling_strategy :oldest
1142
+ #
869
1143
  # @see Puma::Cluster#cull_workers
870
1144
  #
871
1145
  def worker_culling_strategy(strategy)
@@ -878,7 +1152,7 @@ module Puma
878
1152
  @options[:worker_culling_strategy] = strategy
879
1153
  end
880
1154
 
881
- # When set to true (the default), workers accept all requests
1155
+ # When set to true, workers accept all requests
882
1156
  # and queue them before passing them to the handlers.
883
1157
  # When set to false, each worker process accepts exactly as
884
1158
  # many requests as it is configured to simultaneously handle.
@@ -891,7 +1165,11 @@ module Puma
891
1165
  # slow clients will occupy a handler thread while the request
892
1166
  # is being sent. A reverse proxy, such as nginx, can handle
893
1167
  # slow clients and queue requests before they reach Puma.
1168
+ #
1169
+ # The default is +true+.
1170
+ #
894
1171
  # @see Puma::Server
1172
+ #
895
1173
  def queue_requests(answer=true)
896
1174
  @options[:queue_requests] = answer
897
1175
  end
@@ -909,9 +1187,13 @@ module Puma
909
1187
  # listening on the socket, allowing workers which are not processing any
910
1188
  # requests to pick up new requests first.
911
1189
  #
1190
+ # The default is 0.005 seconds.
1191
+ #
912
1192
  # Only works on MRI. For all other interpreters, this setting does nothing.
1193
+ #
913
1194
  # @see Puma::Server#handle_servers
914
1195
  # @see Puma::ThreadPool#wait_for_less_busy_worker
1196
+ #
915
1197
  # @version 5.0.0
916
1198
  #
917
1199
  def wait_for_less_busy_worker(val=0.005)
@@ -925,7 +1207,7 @@ module Puma
925
1207
  #
926
1208
  # There are 5 possible values:
927
1209
  #
928
- # 1. **:socket** (the default) - read the peername from the socket using the
1210
+ # 1. **:socket** - read the peername from the socket using the
929
1211
  # syscall. This is the normal behavior. If this fails for any reason (e.g.,
930
1212
  # if the peer disconnects between the connection being accepted and the getpeername
931
1213
  # system call), Puma will return "0.0.0.0"
@@ -943,6 +1225,11 @@ module Puma
943
1225
  # you wish. Because Puma never uses this field anyway, it's format is
944
1226
  # entirely in your hands.
945
1227
  #
1228
+ # The default is +:socket+.
1229
+ #
1230
+ # @example
1231
+ # set_remote_address :localhost
1232
+ #
946
1233
  def set_remote_address(val=:socket)
947
1234
  case val
948
1235
  when :socket
@@ -983,6 +1270,7 @@ module Puma
983
1270
  # (default 1000), or pass 0 to disable auto refork.
984
1271
  #
985
1272
  # @note Cluster mode only.
1273
+ #
986
1274
  # @version 5.0.0
987
1275
  #
988
1276
  def fork_worker(after_requests=1000)
@@ -992,10 +1280,41 @@ module Puma
992
1280
  # The number of requests to attempt inline before sending a client back to
993
1281
  # the reactor to be subject to normal ordering.
994
1282
  #
1283
+ # The default is 10.
1284
+ #
1285
+ # @example
1286
+ # max_fast_inline 20
1287
+ #
995
1288
  def max_fast_inline(num_of_requests)
996
1289
  @options[:max_fast_inline] = Float(num_of_requests)
997
1290
  end
998
1291
 
1292
+ # When `true`, keep-alive connections are maintained on inbound requests.
1293
+ # Enabling this setting reduces the number of TCP operations, reducing response
1294
+ # times for connections that can send multiple requests in a single connection.
1295
+ #
1296
+ # When Puma receives more incoming connections than available Puma threads,
1297
+ # enabling the keep-alive behavior may result in processing requests out-of-order,
1298
+ # increasing overall response time variance. Increased response time variance
1299
+ # means that the overall average of response times might not change, but more
1300
+ # outliers will exist. Those long-tail outliers may significantly affect response
1301
+ # times for some processed requests.
1302
+ #
1303
+ # When `false`, Puma closes the connection after each request, requiring the
1304
+ # client to open a new request. Disabling this setting guarantees that requests
1305
+ # will be processed in the order they are fully received, decreasing response
1306
+ # variance and eliminating long-tail outliers caused by keep-alive behavior.
1307
+ # The trade-off is that the number of TCP operations required will increase.
1308
+ #
1309
+ # The default is +true+.
1310
+ #
1311
+ # @example
1312
+ # enable_keep_alives false
1313
+ #
1314
+ def enable_keep_alives(enabled=true)
1315
+ @options[:enable_keep_alives] = enabled
1316
+ end
1317
+
999
1318
  # Specify the backend for the IO selector.
1000
1319
  #
1001
1320
  # Provided values will be passed directly to +NIO::Selector.new+, with the
@@ -1015,14 +1334,72 @@ module Puma
1015
1334
  @options[:io_selector_backend] = backend.to_sym
1016
1335
  end
1017
1336
 
1337
+ # Ensures +STDOUT+ and +STDERR+ is immediately flushed to the underlying
1338
+ # operating system and is not buffered internally
1339
+ #
1340
+ # The default is +true+.
1341
+ #
1342
+ # @example
1343
+ # mutate_stdout_and_stderr_to_sync_on_write false
1344
+ #
1018
1345
  def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
1019
1346
  @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
1020
1347
  end
1021
1348
 
1349
+ # Specify how big the request payload should be, in bytes.
1350
+ # This limit is compared against Content-Length HTTP header.
1351
+ # If the payload size (CONTENT_LENGTH) is larger than http_content_length_limit,
1352
+ # HTTP 413 status code is returned.
1353
+ #
1354
+ # When no Content-Length http header is present, it is compared against the
1355
+ # size of the body of the request.
1356
+ #
1357
+ # The default is +nil+.
1358
+ #
1359
+ # @example
1360
+ # http_content_length_limit 2_000_000_000
1361
+ #
1362
+ def http_content_length_limit(limit)
1363
+ @options[:http_content_length_limit] = limit
1364
+ end
1365
+
1366
+ # Supported http methods, which will replace `Puma::Const::SUPPORTED_HTTP_METHODS`.
1367
+ # The value of `:any` will allows all methods, otherwise, the value must be
1368
+ # an array of strings. Note that methods are all uppercase.
1369
+ #
1370
+ # `Puma::Const::SUPPORTED_HTTP_METHODS` is conservative, if you want a
1371
+ # complete set of methods, the methods defined by the
1372
+ # [IANA Method Registry](https://www.iana.org/assignments/http-methods/http-methods.xhtml)
1373
+ # are pre-defined as the constant `Puma::Const::IANA_HTTP_METHODS`.
1374
+ #
1375
+ # @note If the `methods` value is `:any`, no method check with be performed,
1376
+ # similar to Puma v5 and earlier.
1377
+ #
1378
+ # @example Adds 'PROPFIND' to existing supported methods
1379
+ # supported_http_methods(Puma::Const::SUPPORTED_HTTP_METHODS + ['PROPFIND'])
1380
+ # @example Restricts methods to the array elements
1381
+ # supported_http_methods %w[HEAD GET POST PUT DELETE OPTIONS PROPFIND]
1382
+ # @example Restricts methods to the methods in the IANA Registry
1383
+ # supported_http_methods Puma::Const::IANA_HTTP_METHODS
1384
+ # @example Allows any method
1385
+ # supported_http_methods :any
1386
+ #
1387
+ def supported_http_methods(methods)
1388
+ if methods == :any
1389
+ @options[:supported_http_methods] = :any
1390
+ elsif Array === methods && methods == (ary = methods.grep(String).uniq) &&
1391
+ !ary.empty?
1392
+ @options[:supported_http_methods] = ary
1393
+ else
1394
+ raise "supported_http_methods must be ':any' or a unique array of strings"
1395
+ end
1396
+ end
1397
+
1022
1398
  private
1023
1399
 
1024
1400
  # To avoid adding cert_pem and key_pem as URI params, we store them on the
1025
1401
  # options[:store] from where Puma binder knows how to find and extract them.
1402
+ #
1026
1403
  def add_pem_values_to_options_store(opts)
1027
1404
  return if defined?(JRUBY_VERSION)
1028
1405
 
@@ -1046,7 +1423,22 @@ module Puma
1046
1423
  elsif key.nil?
1047
1424
  @options[options_key] << block
1048
1425
  else
1049
- raise "'#{method}' key must be String or Symbol"
1426
+ raise "'#{meth}' key must be String or Symbol"
1427
+ end
1428
+ end
1429
+
1430
+ def warn_if_in_single_mode(hook_name)
1431
+ return if @options[:silence_fork_callback_warning]
1432
+ # user_options (CLI) have precedence over config file
1433
+ workers_val = @config.options.user_options[:workers] || @options[:workers] ||
1434
+ @config.puma_default_options[:workers] || 0
1435
+ if workers_val == 0
1436
+ log_string =
1437
+ "Warning: You specified code to run in a `#{hook_name}` block, " \
1438
+ "but Puma is not configured to run in cluster mode (worker count > 0), " \
1439
+ "so your `#{hook_name}` block will not run."
1440
+
1441
+ LogWriter.stdio.log(log_string)
1050
1442
  end
1051
1443
  end
1052
1444
  end