puma 3.12.0 → 4.3.8

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +164 -0
  3. data/README.md +76 -48
  4. data/docs/architecture.md +1 -0
  5. data/docs/deployment.md +24 -4
  6. data/docs/plugins.md +20 -10
  7. data/docs/restart.md +4 -2
  8. data/docs/systemd.md +27 -9
  9. data/docs/tcp_mode.md +96 -0
  10. data/ext/puma_http11/PumaHttp11Service.java +2 -0
  11. data/ext/puma_http11/extconf.rb +13 -0
  12. data/ext/puma_http11/http11_parser.c +40 -63
  13. data/ext/puma_http11/http11_parser.java.rl +21 -37
  14. data/ext/puma_http11/http11_parser.rl +3 -1
  15. data/ext/puma_http11/http11_parser_common.rl +3 -3
  16. data/ext/puma_http11/mini_ssl.c +86 -4
  17. data/ext/puma_http11/org/jruby/puma/Http11.java +106 -114
  18. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +91 -106
  19. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
  20. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +15 -4
  21. data/ext/puma_http11/puma_http11.c +3 -0
  22. data/lib/puma.rb +8 -0
  23. data/lib/puma/accept_nonblock.rb +7 -1
  24. data/lib/puma/app/status.rb +37 -29
  25. data/lib/puma/binder.rb +47 -68
  26. data/lib/puma/cli.rb +6 -0
  27. data/lib/puma/client.rb +244 -199
  28. data/lib/puma/cluster.rb +55 -30
  29. data/lib/puma/commonlogger.rb +2 -0
  30. data/lib/puma/configuration.rb +6 -3
  31. data/lib/puma/const.rb +32 -18
  32. data/lib/puma/control_cli.rb +41 -14
  33. data/lib/puma/detect.rb +2 -0
  34. data/lib/puma/dsl.rb +311 -77
  35. data/lib/puma/events.rb +6 -1
  36. data/lib/puma/io_buffer.rb +3 -6
  37. data/lib/puma/jruby_restart.rb +2 -0
  38. data/lib/puma/launcher.rb +99 -55
  39. data/lib/puma/minissl.rb +37 -17
  40. data/lib/puma/minissl/context_builder.rb +76 -0
  41. data/lib/puma/null_io.rb +2 -0
  42. data/lib/puma/plugin.rb +7 -2
  43. data/lib/puma/plugin/tmp_restart.rb +2 -0
  44. data/lib/puma/rack/builder.rb +4 -1
  45. data/lib/puma/rack/urlmap.rb +2 -0
  46. data/lib/puma/rack_default.rb +2 -0
  47. data/lib/puma/reactor.rb +112 -57
  48. data/lib/puma/runner.rb +13 -3
  49. data/lib/puma/server.rb +119 -48
  50. data/lib/puma/single.rb +5 -3
  51. data/lib/puma/state_file.rb +2 -0
  52. data/lib/puma/tcp_logger.rb +2 -0
  53. data/lib/puma/thread_pool.rb +17 -33
  54. data/lib/puma/util.rb +2 -6
  55. data/lib/rack/handler/puma.rb +6 -3
  56. data/tools/docker/Dockerfile +16 -0
  57. data/tools/jungle/init.d/puma +6 -6
  58. data/tools/trickletest.rb +0 -1
  59. metadata +26 -14
  60. data/lib/puma/compat.rb +0 -14
  61. data/lib/puma/convenient.rb +0 -23
  62. data/lib/puma/daemon_ext.rb +0 -31
  63. data/lib/puma/delegation.rb +0 -11
  64. data/lib/puma/java_io_buffer.rb +0 -45
  65. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
data/lib/puma/detect.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Puma
2
4
  IS_JRUBY = defined?(JRUBY_VERSION)
3
5
 
data/lib/puma/dsl.rb CHANGED
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/const'
4
+
1
5
  module Puma
2
- # The methods that are available for use inside the config file.
6
+ # The methods that are available for use inside the configuration file.
3
7
  # These same methods are used in Puma cli and the rack handler
4
8
  # internally.
5
9
  #
@@ -24,7 +28,8 @@ module Puma
24
28
  # puts config.options[:binds]
25
29
  # # => "tcp://127.0.0.1:3002"
26
30
  #
27
- # Detailed docs can be found in `examples/config.rb`
31
+ # You can also find many examples being used by the test suite in
32
+ # +test/config+.
28
33
  class DSL
29
34
  include ConfigDefault
30
35
 
@@ -55,6 +60,14 @@ module Puma
55
60
  @plugins.clear
56
61
  end
57
62
 
63
+ def set_default_host(host)
64
+ @options[:default_host] = host
65
+ end
66
+
67
+ def default_host
68
+ @options[:default_host] || Configuration::DefaultTCPHost
69
+ end
70
+
58
71
  def inject(&blk)
59
72
  instance_eval(&blk)
60
73
  end
@@ -69,9 +82,22 @@ module Puma
69
82
  @plugins << @config.load_plugin(name)
70
83
  end
71
84
 
72
- # Use +obj+ or +block+ as the Rack app. This allows a config file to
73
- # be the app itself.
85
+ # Use an object or block as the rack application. This allows the
86
+ # configuration file to be the application itself.
87
+ #
88
+ # @example
89
+ # app do |env|
90
+ # body = 'Hello, World!'
74
91
  #
92
+ # [
93
+ # 200,
94
+ # {
95
+ # 'Content-Type' => 'text/plain',
96
+ # 'Content-Length' => body.length.to_s
97
+ # },
98
+ # [body]
99
+ # ]
100
+ # end
75
101
  def app(obj=nil, &block)
76
102
  obj ||= block
77
103
 
@@ -80,9 +106,20 @@ module Puma
80
106
  @options[:app] = obj
81
107
  end
82
108
 
83
- # Start the Puma control rack app on +url+. This app can be communicated
84
- # with to control the main server.
109
+ # Start the Puma control rack application on +url+. This application can
110
+ # be communicated with to control the main server. Additionally, you can
111
+ # provide an authentication token, so all requests to the control server
112
+ # will need to include that token as a query parameter. This allows for
113
+ # simple authentication.
85
114
  #
115
+ # Check out {Puma::App::Status} to see what the app has available.
116
+ #
117
+ # @example
118
+ # activate_control_app 'unix:///var/run/pumactl.sock'
119
+ # @example
120
+ # activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
121
+ # @example
122
+ # activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
86
123
  def activate_control_app(url="auto", opts={})
87
124
  if url == "auto"
88
125
  path = Configuration.temp_path
@@ -93,7 +130,12 @@ module Puma
93
130
  end
94
131
 
95
132
  if opts[:no_token]
96
- auth_token = :none
133
+ # We need to use 'none' rather than :none because this value will be
134
+ # passed on to an instance of OptionParser, which doesn't support
135
+ # symbols as option values.
136
+ #
137
+ # See: https://github.com/puma/puma/issues/1193#issuecomment-305995488
138
+ auth_token = 'none'
97
139
  else
98
140
  auth_token = opts[:auth_token]
99
141
  auth_token ||= Configuration.random_token
@@ -110,22 +152,29 @@ module Puma
110
152
  @options[:config_files] << file
111
153
  end
112
154
 
113
- # Adds a binding for the server to +url+. tcp://, unix://, and ssl:// are the only accepted
114
- # protocols. Use query parameters within the url to specify options.
115
- #
116
- # @note multiple urls can be bound to, calling `bind` does not overwrite previous bindings.
155
+ # Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
156
+ # accepted protocols. Multiple urls can be bound to, calling `bind` does
157
+ # not overwrite previous bindings.
117
158
  #
118
- # @example Explicitly the socket backlog depth (default is 1024)
119
- # bind('unix:///var/run/puma.sock?backlog=2048')
159
+ # The default is "tcp://0.0.0.0:9292".
120
160
  #
121
- # @example Set up ssl cert
122
- # bind('ssl://127.0.0.1:9292?key=key.key&cert=cert.pem')
161
+ # You can use query parameters within the url to specify options:
123
162
  #
124
- # @example Prefer low-latency over higher throughput (via `Socket::TCP_NODELAY`)
125
- # bind('tcp://0.0.0.0:9292?low_latency=true')
163
+ # - Set the socket backlog depth with +backlog+, default is 1024.
164
+ # - Set up an SSL certificate with +key+ & +cert+.
165
+ # - Set whether to optimize for low latency instead of throughput with
166
+ # +low_latency+, default is to optimize for low latency. This is done
167
+ # via +Socket::TCP_NODELAY+.
168
+ # - Set socket permissions with +umask+.
126
169
  #
127
- # @example Set socket permissions
128
- # bind('unix:///var/run/puma.sock?umask=0111')
170
+ # @example Backlog depth
171
+ # bind 'unix:///var/run/puma.sock?backlog=512'
172
+ # @example SSL cert
173
+ # bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
174
+ # @example Disable optimization for low latency
175
+ # bind 'tcp://0.0.0.0:9292?low_latency=false'
176
+ # @example Socket permissions
177
+ # bind 'unix:///var/run/puma.sock?umask=0111'
129
178
  def bind(url)
130
179
  @options[:binds] ||= []
131
180
  @options[:binds] << url
@@ -137,33 +186,40 @@ module Puma
137
186
 
138
187
  # Define the TCP port to bind to. Use +bind+ for more advanced options.
139
188
  #
189
+ # @example
190
+ # port 9292
140
191
  def port(port, host=nil)
141
- host ||= Configuration::DefaultTCPHost
192
+ host ||= default_host
142
193
  bind "tcp://#{host}:#{port}"
143
194
  end
144
195
 
145
- # Define how long persistent connections can be idle before puma closes
146
- # them
147
- #
196
+ # Define how long persistent connections can be idle before Puma closes
197
+ # them.
148
198
  def persistent_timeout(seconds)
149
199
  @options[:persistent_timeout] = Integer(seconds)
150
200
  end
151
201
 
152
- # Define how long the tcp socket stays open, if no data has been received
153
- #
202
+ # Define how long the tcp socket stays open, if no data has been received.
154
203
  def first_data_timeout(seconds)
155
204
  @options[:first_data_timeout] = Integer(seconds)
156
205
  end
157
206
 
158
207
  # Work around leaky apps that leave garbage in Thread locals
159
- # across requests
160
- #
208
+ # across requests.
161
209
  def clean_thread_locals(which=true)
162
210
  @options[:clean_thread_locals] = which
163
211
  end
164
212
 
165
- # Daemonize the server into the background. Highly suggest that
166
- # this be combined with +pidfile+ and +stdout_redirect+.
213
+ # Daemonize the server into the background. It's highly recommended to
214
+ # use this in combination with +pidfile+ and +stdout_redirect+.
215
+ #
216
+ # The default is "false".
217
+ #
218
+ # @example
219
+ # daemonize
220
+ #
221
+ # @example
222
+ # daemonize false
167
223
  def daemonize(which=true)
168
224
  @options[:daemon] = which
169
225
  end
@@ -176,7 +232,13 @@ module Puma
176
232
  @options[:drain_on_shutdown] = which
177
233
  end
178
234
 
179
- # Set the environment in which the Rack's app will run.
235
+ # Set the environment in which the rack's app will run. The value must be
236
+ # a string.
237
+ #
238
+ # The default is "development".
239
+ #
240
+ # @example
241
+ # environment 'production'
180
242
  def environment(environment)
181
243
  @options[:environment] = environment
182
244
  end
@@ -202,30 +264,41 @@ module Puma
202
264
  end
203
265
 
204
266
  # Code to run before doing a restart. This code should
205
- # close logfiles, database connections, etc.
267
+ # close log files, database connections, etc.
206
268
  #
207
269
  # This can be called multiple times to add code each time.
208
270
  #
271
+ # @example
272
+ # on_restart do
273
+ # puts 'On restart...'
274
+ # end
209
275
  def on_restart(&block)
210
276
  @options[:on_restart] ||= []
211
277
  @options[:on_restart] << block
212
278
  end
213
279
 
214
- # Command to use to restart puma. This should be just how to
215
- # load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
216
- # to puma, as those are the same as the original process.
280
+ # Command to use to restart Puma. This should be just how to
281
+ # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
282
+ # to Puma, as those are the same as the original process.
217
283
  #
284
+ # @example
285
+ # restart_command '/u/app/lolcat/bin/restart_puma'
218
286
  def restart_command(cmd)
219
287
  @options[:restart_cmd] = cmd.to_s
220
288
  end
221
289
 
222
- # Store the pid of the server in the file at +path+.
290
+ # Store the pid of the server in the file at "path".
291
+ #
292
+ # @example
293
+ # pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
223
294
  def pidfile(path)
224
295
  @options[:pidfile] = path.to_s
225
296
  end
226
297
 
227
- # Disable request logging.
298
+ # Disable request logging, if this isn't used it'll be enabled by default.
228
299
  #
300
+ # @example
301
+ # quiet
229
302
  def quiet(which=true)
230
303
  @options[:log_requests] = !which
231
304
  end
@@ -244,6 +317,10 @@ module Puma
244
317
 
245
318
  # Load +path+ as a rackup file.
246
319
  #
320
+ # The default is "config.ru".
321
+ #
322
+ # @example
323
+ # rackup '/u/apps/lolcat/config.ru'
247
324
  def rackup(path)
248
325
  @options[:rackup] = path.to_s
249
326
  end
@@ -258,16 +335,32 @@ module Puma
258
335
  @options[:early_hints] = answer
259
336
  end
260
337
 
261
- # Redirect STDOUT and STDERR to files specified.
338
+ # Redirect STDOUT and STDERR to files specified. The +append+ parameter
339
+ # specifies whether the output is appended, the default is +false+.
340
+ #
341
+ # @example
342
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
343
+ # @example
344
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
262
345
  def stdout_redirect(stdout=nil, stderr=nil, append=false)
263
346
  @options[:redirect_stdout] = stdout
264
347
  @options[:redirect_stderr] = stderr
265
348
  @options[:redirect_append] = append
266
349
  end
267
350
 
351
+ def log_formatter(&block)
352
+ @options[:log_formatter] = block
353
+ end
354
+
268
355
  # Configure +min+ to be the minimum number of threads to use to answer
269
356
  # requests and +max+ the maximum.
270
357
  #
358
+ # The default is "0, 16".
359
+ #
360
+ # @example
361
+ # threads 0, 16
362
+ # @example
363
+ # threads 5, 5
271
364
  def threads(min, max)
272
365
  min = Integer(min)
273
366
  max = Integer(max)
@@ -283,81 +376,135 @@ module Puma
283
376
  @options[:max_threads] = max
284
377
  end
285
378
 
379
+ # Instead of "bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'" you
380
+ # can also use the "ssl_bind" option.
381
+ #
382
+ # @example
383
+ # ssl_bind '127.0.0.1', '9292', {
384
+ # cert: path_to_cert,
385
+ # key: path_to_key,
386
+ # ssl_cipher_filter: cipher_filter, # optional
387
+ # verify_mode: verify_mode, # default 'none'
388
+ # }
389
+ # @example For JRuby additional keys are required: keystore & keystore_pass.
390
+ # ssl_bind '127.0.0.1', '9292', {
391
+ # cert: path_to_cert,
392
+ # key: path_to_key,
393
+ # ssl_cipher_filter: cipher_filter, # optional
394
+ # verify_mode: verify_mode, # default 'none'
395
+ # keystore: path_to_keystore,
396
+ # keystore_pass: password
397
+ # }
286
398
  def ssl_bind(host, port, opts)
287
- verify = opts.fetch(:verify_mode, 'none')
399
+ verify = opts.fetch(:verify_mode, 'none').to_s
400
+ no_tlsv1 = opts.fetch(:no_tlsv1, 'false')
401
+ no_tlsv1_1 = opts.fetch(:no_tlsv1_1, 'false')
402
+ ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
288
403
 
289
404
  if defined?(JRUBY_VERSION)
290
405
  keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
291
- bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}"
406
+ bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
292
407
  else
293
- bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&verify_mode=#{verify}"
408
+ ssl_cipher_filter = "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" if opts[:ssl_cipher_filter]
409
+ bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}#{ssl_cipher_filter}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
294
410
  end
295
411
  end
296
412
 
297
413
  # Use +path+ as the file to store the server info state. This is
298
- # used by pumactl to query and control the server.
414
+ # used by +pumactl+ to query and control the server.
299
415
  #
416
+ # @example
417
+ # state_path '/u/apps/lolcat/tmp/pids/puma.state'
300
418
  def state_path(path)
301
419
  @options[:state] = path.to_s
302
420
  end
303
421
 
304
- # *Cluster mode only* How many worker processes to run.
422
+ # How many worker processes to run. Typically this is set to
423
+ # to the number of available cores.
424
+ #
425
+ # The default is 0.
305
426
  #
427
+ # @note Cluster mode only.
306
428
  def workers(count)
307
429
  @options[:workers] = count.to_i
308
430
  end
309
431
 
310
- # *Cluster mode only* Code to run immediately before master process
432
+ # Code to run immediately before master process
311
433
  # forks workers (once on boot). These hooks can block if necessary
312
- # to wait for background operations unknown to puma to finish before
434
+ # to wait for background operations unknown to Puma to finish before
313
435
  # the process terminates.
314
- # This can be used to close any connections to remote servers (database, redis, ...)
315
- # that were opened when preloading the code
436
+ # This can be used to close any connections to remote servers (database,
437
+ # Redis, ...) that were opened when preloading the code.
316
438
  #
317
- # This can be called multiple times to add hooks.
439
+ # This can be called multiple times to add several hooks.
318
440
  #
441
+ # @note Cluster mode only.
442
+ # @example
443
+ # before_fork do
444
+ # puts "Starting workers..."
445
+ # end
319
446
  def before_fork(&block)
320
447
  @options[:before_fork] ||= []
321
448
  @options[:before_fork] << block
322
449
  end
323
450
 
324
- # *Cluster mode only* Code to run in a worker when it boots to setup
451
+ # Code to run in a worker when it boots to setup
325
452
  # the process before booting the app.
326
453
  #
327
- # This can be called multiple times to add hooks.
454
+ # This can be called multiple times to add several hooks.
328
455
  #
456
+ # @note Cluster mode only.
457
+ # @example
458
+ # on_worker_fork do
459
+ # puts 'Before worker fork...'
460
+ # end
329
461
  def on_worker_boot(&block)
330
462
  @options[:before_worker_boot] ||= []
331
463
  @options[:before_worker_boot] << block
332
464
  end
333
465
 
334
- # *Cluster mode only* Code to run immediately before a worker shuts
466
+ # Code to run immediately before a worker shuts
335
467
  # down (after it has finished processing HTTP requests). These hooks
336
468
  # can block if necessary to wait for background operations unknown
337
- # to puma to finish before the process terminates.
469
+ # to Puma to finish before the process terminates.
338
470
  #
339
- # This can be called multiple times to add hooks.
471
+ # This can be called multiple times to add several hooks.
340
472
  #
473
+ # @note Cluster mode only.
474
+ # @example
475
+ # on_worker_shutdown do
476
+ # puts 'On worker shutdown...'
477
+ # end
341
478
  def on_worker_shutdown(&block)
342
479
  @options[:before_worker_shutdown] ||= []
343
480
  @options[:before_worker_shutdown] << block
344
481
  end
345
482
 
346
- # *Cluster mode only* Code to run in the master when it is
347
- # about to create the worker by forking itself.
483
+ # Code to run in the master right before a worker is started. The worker's
484
+ # index is passed as an argument.
348
485
  #
349
- # This can be called multiple times to add hooks.
486
+ # This can be called multiple times to add several hooks.
350
487
  #
488
+ # @note Cluster mode only.
489
+ # @example
490
+ # on_worker_fork do
491
+ # puts 'Before worker fork...'
492
+ # end
351
493
  def on_worker_fork(&block)
352
494
  @options[:before_worker_fork] ||= []
353
495
  @options[:before_worker_fork] << block
354
496
  end
355
497
 
356
- # *Cluster mode only* Code to run in the master after it starts
357
- # a worker.
498
+ # Code to run in the master after a worker has been started. The worker's
499
+ # index is passed as an argument.
358
500
  #
359
- # This can be called multiple times to add hooks.
501
+ # This is called everytime a worker is to be started.
360
502
  #
503
+ # @note Cluster mode only.
504
+ # @example
505
+ # after_worker_fork do
506
+ # puts 'After worker fork...'
507
+ # end
361
508
  def after_worker_fork(&block)
362
509
  @options[:after_worker_fork] ||= []
363
510
  @options[:after_worker_fork] = block
@@ -365,7 +512,26 @@ module Puma
365
512
 
366
513
  alias_method :after_worker_boot, :after_worker_fork
367
514
 
515
+ # Code to run out-of-band when the worker is idle.
516
+ # These hooks run immediately after a request has finished
517
+ # processing and there are no busy threads on the worker.
518
+ # The worker doesn't accept new requests until this code finishes.
519
+ #
520
+ # This hook is useful for running out-of-band garbage collection
521
+ # or scheduling asynchronous tasks to execute after a response.
522
+ #
523
+ # This can be called multiple times to add several hooks.
524
+ def out_of_band(&block)
525
+ @options[:out_of_band] ||= []
526
+ @options[:out_of_band] << block
527
+ end
528
+
368
529
  # The directory to operate out of.
530
+ #
531
+ # The default is the current directory.
532
+ #
533
+ # @example
534
+ # directory '/u/apps/lolcat'
369
535
  def directory(dir)
370
536
  @options[:directory] = dir.to_s
371
537
  end
@@ -376,22 +542,28 @@ module Puma
376
542
  directory dir
377
543
  end
378
544
 
379
- # Run the app as a raw TCP app instead of an HTTP rack app
545
+ # Run the app as a raw TCP app instead of an HTTP rack app.
380
546
  def tcp_mode
381
547
  @options[:mode] = :tcp
382
548
  end
383
549
 
384
- # *Cluster mode only* Preload the application before starting
385
- # the workers and setting up the listen ports. This conflicts
386
- # with using the phased restart feature, you can't use both.
550
+ # Preload the application before starting the workers; this conflicts with
551
+ # phased restart feature. This is off by default.
387
552
  #
553
+ # @note Cluster mode only.
554
+ # @example
555
+ # preload_app!
388
556
  def preload_app!(answer=true)
389
557
  @options[:preload_app] = answer
390
558
  end
391
559
 
392
- # Use +obj+ or +block+ as the low level error handler. This allows a config file to
393
- # change the default error on the server.
560
+ # Use +obj+ or +block+ as the low level error handler. This allows the
561
+ # configuration file to change the default error on the server.
394
562
  #
563
+ # @example
564
+ # lowlevel_error_handler do |err|
565
+ # [200, {}, ["error page"]]
566
+ # end
395
567
  def lowlevel_error_handler(obj=nil, &block)
396
568
  obj ||= block
397
569
  raise "Provide either a #call'able or a block" unless obj
@@ -401,38 +573,100 @@ module Puma
401
573
  # This option is used to allow your app and its gems to be
402
574
  # properly reloaded when not using preload.
403
575
  #
404
- # When set, if puma detects that it's been invoked in the
576
+ # When set, if Puma detects that it's been invoked in the
405
577
  # context of Bundler, it will cleanup the environment and
406
578
  # re-run itself outside the Bundler environment, but directly
407
579
  # using the files that Bundler has setup.
408
580
  #
409
- # This means that puma is now decoupled from your Bundler
581
+ # This means that Puma is now decoupled from your Bundler
410
582
  # context and when each worker loads, it will be loading a
411
583
  # new Bundler context and thus can float around as the release
412
584
  # dictates.
585
+ #
586
+ # See also: extra_runtime_dependencies
587
+ #
588
+ # @note This is incompatible with +preload_app!+.
589
+ # @note This is only supported for RubyGems 2.2+
413
590
  def prune_bundler(answer=true)
414
591
  @options[:prune_bundler] = answer
415
592
  end
416
593
 
417
- # Additional text to display in process listing
594
+ # By default, Puma will raise SignalException when SIGTERM is received. In
595
+ # environments where SIGTERM is something expected, you can suppress these
596
+ # with this option.
597
+ #
598
+ # This can be useful for example in Kubernetes, where rolling restart is
599
+ # guaranteed usually on infrastructure level.
600
+ #
601
+ # @example
602
+ # raise_exception_on_sigterm false
603
+ def raise_exception_on_sigterm(answer=true)
604
+ @options[:raise_exception_on_sigterm] = answer
605
+ end
606
+
607
+ # When using prune_bundler, if extra runtime dependencies need to be loaded to
608
+ # initialize your app, then this setting can be used. This includes any Puma plugins.
609
+ #
610
+ # Before bundler is pruned, the gem names supplied will be looked up in the bundler
611
+ # context and then loaded again after bundler is pruned.
612
+ # Only applies if prune_bundler is used.
613
+ #
614
+ # @example
615
+ # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
616
+ # @example
617
+ # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
618
+ def extra_runtime_dependencies(answer = [])
619
+ @options[:extra_runtime_dependencies] = Array(answer)
620
+ end
621
+
622
+ # Additional text to display in process listing.
623
+ #
624
+ # If you do not specify a tag, Puma will infer it. If you do not want Puma
625
+ # to add a tag, use an empty string.
626
+ #
627
+ # @example
628
+ # tag 'app name'
629
+ # @example
630
+ # tag ''
418
631
  def tag(string)
419
632
  @options[:tag] = string.to_s
420
633
  end
421
634
 
422
- # *Cluster mode only* Set the timeout for workers in seconds
423
- # When set the master process will terminate any workers
424
- # that have not checked in within the given +timeout+.
425
- # This mitigates hung processes. Default value is 60 seconds.
635
+ # Verifies that all workers have checked in to the master process within
636
+ # the given timeout. If not the worker process will be restarted. This is
637
+ # not a request timeout, it is to protect against a hung or dead process.
638
+ # Setting this value will not protect against slow requests.
639
+ #
640
+ # The minimum value is 6 seconds, the default value is 60 seconds.
641
+ #
642
+ # @note Cluster mode only.
643
+ # @example
644
+ # worker_timeout 60
426
645
  def worker_timeout(timeout)
427
- @options[:worker_timeout] = Integer(timeout)
646
+ timeout = Integer(timeout)
647
+ min = Const::WORKER_CHECK_INTERVAL
648
+
649
+ if timeout <= min
650
+ raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
651
+ end
652
+
653
+ @options[:worker_timeout] = timeout
428
654
  end
429
655
 
430
- # *Cluster mode only* Set the timeout for workers to boot
656
+ # Change the default worker timeout for booting.
657
+ #
658
+ # If unspecified, this defaults to the value of worker_timeout.
659
+ #
660
+ # @note Cluster mode only.
661
+ # @example:
662
+ # worker_boot_timeout 60
431
663
  def worker_boot_timeout(timeout)
432
664
  @options[:worker_boot_timeout] = Integer(timeout)
433
665
  end
434
666
 
435
- # *Cluster mode only* Set the timeout for worker shutdown
667
+ # Set the timeout for worker shutdown
668
+ #
669
+ # @note Cluster mode only.
436
670
  def worker_shutdown_timeout(timeout)
437
671
  @options[:worker_shutdown_timeout] = Integer(timeout)
438
672
  end
@@ -449,7 +683,7 @@ module Puma
449
683
  # Note that setting this to false disables HTTP keepalive and
450
684
  # slow clients will occupy a handler thread while the request
451
685
  # is being sent. A reverse proxy, such as nginx, can handle
452
- # slow clients and queue requests before they reach puma.
686
+ # slow clients and queue requests before they reach Puma.
453
687
  def queue_requests(answer=true)
454
688
  @options[:queue_requests] = answer
455
689
  end
@@ -478,7 +712,7 @@ module Puma
478
712
  # is used, allowing headers such as X-Forwarded-For
479
713
  # to be used as well.
480
714
  # * Any string - this allows you to hardcode remote address to any value
481
- # you wish. Because puma never uses this field anyway, it's
715
+ # you wish. Because Puma never uses this field anyway, it's
482
716
  # format is entirely in your hands.
483
717
  def set_remote_address(val=:socket)
484
718
  case val
@@ -493,7 +727,7 @@ module Puma
493
727
  when Hash
494
728
  if hdr = val[:header]
495
729
  @options[:remote_address] = :header
496
- @options[:remote_address_header] = "HTTP_" + hdr.upcase.gsub("-", "_")
730
+ @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
497
731
  else
498
732
  raise "Invalid value for set_remote_address - #{val.inspect}"
499
733
  end