puma 4.3.0

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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +1532 -0
  3. data/LICENSE +26 -0
  4. data/README.md +291 -0
  5. data/bin/puma +10 -0
  6. data/bin/puma-wild +31 -0
  7. data/bin/pumactl +12 -0
  8. data/docs/architecture.md +37 -0
  9. data/docs/deployment.md +111 -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/nginx.md +80 -0
  14. data/docs/plugins.md +38 -0
  15. data/docs/restart.md +41 -0
  16. data/docs/signals.md +96 -0
  17. data/docs/systemd.md +290 -0
  18. data/docs/tcp_mode.md +96 -0
  19. data/ext/puma_http11/PumaHttp11Service.java +19 -0
  20. data/ext/puma_http11/ext_help.h +15 -0
  21. data/ext/puma_http11/extconf.rb +28 -0
  22. data/ext/puma_http11/http11_parser.c +1044 -0
  23. data/ext/puma_http11/http11_parser.h +65 -0
  24. data/ext/puma_http11/http11_parser.java.rl +145 -0
  25. data/ext/puma_http11/http11_parser.rl +147 -0
  26. data/ext/puma_http11/http11_parser_common.rl +54 -0
  27. data/ext/puma_http11/io_buffer.c +155 -0
  28. data/ext/puma_http11/mini_ssl.c +553 -0
  29. data/ext/puma_http11/org/jruby/puma/Http11.java +226 -0
  30. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +455 -0
  31. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
  32. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +363 -0
  33. data/ext/puma_http11/puma_http11.c +502 -0
  34. data/lib/puma.rb +31 -0
  35. data/lib/puma/accept_nonblock.rb +29 -0
  36. data/lib/puma/app/status.rb +80 -0
  37. data/lib/puma/binder.rb +385 -0
  38. data/lib/puma/cli.rb +239 -0
  39. data/lib/puma/client.rb +494 -0
  40. data/lib/puma/cluster.rb +554 -0
  41. data/lib/puma/commonlogger.rb +108 -0
  42. data/lib/puma/configuration.rb +362 -0
  43. data/lib/puma/const.rb +235 -0
  44. data/lib/puma/control_cli.rb +289 -0
  45. data/lib/puma/detect.rb +15 -0
  46. data/lib/puma/dsl.rb +740 -0
  47. data/lib/puma/events.rb +156 -0
  48. data/lib/puma/io_buffer.rb +4 -0
  49. data/lib/puma/jruby_restart.rb +84 -0
  50. data/lib/puma/launcher.rb +475 -0
  51. data/lib/puma/minissl.rb +278 -0
  52. data/lib/puma/minissl/context_builder.rb +76 -0
  53. data/lib/puma/null_io.rb +44 -0
  54. data/lib/puma/plugin.rb +120 -0
  55. data/lib/puma/plugin/tmp_restart.rb +36 -0
  56. data/lib/puma/rack/builder.rb +301 -0
  57. data/lib/puma/rack/urlmap.rb +93 -0
  58. data/lib/puma/rack_default.rb +9 -0
  59. data/lib/puma/reactor.rb +400 -0
  60. data/lib/puma/runner.rb +192 -0
  61. data/lib/puma/server.rb +1030 -0
  62. data/lib/puma/single.rb +123 -0
  63. data/lib/puma/state_file.rb +31 -0
  64. data/lib/puma/tcp_logger.rb +41 -0
  65. data/lib/puma/thread_pool.rb +328 -0
  66. data/lib/puma/util.rb +124 -0
  67. data/lib/rack/handler/puma.rb +115 -0
  68. data/tools/docker/Dockerfile +16 -0
  69. data/tools/jungle/README.md +19 -0
  70. data/tools/jungle/init.d/README.md +61 -0
  71. data/tools/jungle/init.d/puma +421 -0
  72. data/tools/jungle/init.d/run-puma +18 -0
  73. data/tools/jungle/rc.d/README.md +74 -0
  74. data/tools/jungle/rc.d/puma +61 -0
  75. data/tools/jungle/rc.d/puma.conf +10 -0
  76. data/tools/jungle/upstart/README.md +61 -0
  77. data/tools/jungle/upstart/puma-manager.conf +31 -0
  78. data/tools/jungle/upstart/puma.conf +69 -0
  79. data/tools/trickletest.rb +44 -0
  80. metadata +144 -0
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Puma
4
+ IS_JRUBY = defined?(JRUBY_VERSION)
5
+
6
+ def self.jruby?
7
+ IS_JRUBY
8
+ end
9
+
10
+ IS_WINDOWS = RUBY_PLATFORM =~ /mswin|ming|cygwin/
11
+
12
+ def self.windows?
13
+ IS_WINDOWS
14
+ end
15
+ end
@@ -0,0 +1,740 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/const'
4
+
5
+ module Puma
6
+ # The methods that are available for use inside the configuration file.
7
+ # These same methods are used in Puma cli and the rack handler
8
+ # internally.
9
+ #
10
+ # Used manually (via CLI class):
11
+ #
12
+ # config = Configuration.new({}) do |user_config|
13
+ # user_config.port 3001
14
+ # end
15
+ # config.load
16
+ #
17
+ # puts config.options[:binds]
18
+ # "tcp://127.0.0.1:3001"
19
+ #
20
+ # Used to load file:
21
+ #
22
+ # $ cat puma_config.rb
23
+ # port 3002
24
+ #
25
+ # config = Configuration.new(config_file: "puma_config.rb")
26
+ # config.load
27
+ #
28
+ # puts config.options[:binds]
29
+ # # => "tcp://127.0.0.1:3002"
30
+ #
31
+ # You can also find many examples being used by the test suite in
32
+ # +test/config+.
33
+ class DSL
34
+ include ConfigDefault
35
+
36
+ def initialize(options, config)
37
+ @config = config
38
+ @options = options
39
+
40
+ @plugins = []
41
+ end
42
+
43
+ def _load_from(path)
44
+ if path
45
+ @path = path
46
+ instance_eval(File.read(path), path, 1)
47
+ end
48
+ ensure
49
+ _offer_plugins
50
+ end
51
+
52
+ def _offer_plugins
53
+ @plugins.each do |o|
54
+ if o.respond_to? :config
55
+ @options.shift
56
+ o.config self
57
+ end
58
+ end
59
+
60
+ @plugins.clear
61
+ end
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
+
71
+ def inject(&blk)
72
+ instance_eval(&blk)
73
+ end
74
+
75
+ def get(key,default=nil)
76
+ @options[key.to_sym] || default
77
+ end
78
+
79
+ # Load the named plugin for use by this configuration
80
+ #
81
+ def plugin(name)
82
+ @plugins << @config.load_plugin(name)
83
+ end
84
+
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!'
91
+ #
92
+ # [
93
+ # 200,
94
+ # {
95
+ # 'Content-Type' => 'text/plain',
96
+ # 'Content-Length' => body.length.to_s
97
+ # },
98
+ # [body]
99
+ # ]
100
+ # end
101
+ def app(obj=nil, &block)
102
+ obj ||= block
103
+
104
+ raise "Provide either a #call'able or a block" unless obj
105
+
106
+ @options[:app] = obj
107
+ end
108
+
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.
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 }
123
+ def activate_control_app(url="auto", opts={})
124
+ if url == "auto"
125
+ path = Configuration.temp_path
126
+ @options[:control_url] = "unix://#{path}"
127
+ @options[:control_url_temp] = path
128
+ else
129
+ @options[:control_url] = url
130
+ end
131
+
132
+ if opts[:no_token]
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'
139
+ else
140
+ auth_token = opts[:auth_token]
141
+ auth_token ||= Configuration.random_token
142
+ end
143
+
144
+ @options[:control_auth_token] = auth_token
145
+ @options[:control_url_umask] = opts[:umask] if opts[:umask]
146
+ end
147
+
148
+ # Load additional configuration from a file
149
+ # Files get loaded later via Configuration#load
150
+ def load(file)
151
+ @options[:config_files] ||= []
152
+ @options[:config_files] << file
153
+ end
154
+
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.
158
+ #
159
+ # The default is "tcp://0.0.0.0:9292".
160
+ #
161
+ # You can use query parameters within the url to specify options:
162
+ #
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+.
169
+ #
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'
178
+ def bind(url)
179
+ @options[:binds] ||= []
180
+ @options[:binds] << url
181
+ end
182
+
183
+ def clear_binds!
184
+ @options[:binds] = []
185
+ end
186
+
187
+ # Define the TCP port to bind to. Use +bind+ for more advanced options.
188
+ #
189
+ # @example
190
+ # port 9292
191
+ def port(port, host=nil)
192
+ host ||= default_host
193
+ bind "tcp://#{host}:#{port}"
194
+ end
195
+
196
+ # Define how long persistent connections can be idle before Puma closes
197
+ # them.
198
+ def persistent_timeout(seconds)
199
+ @options[:persistent_timeout] = Integer(seconds)
200
+ end
201
+
202
+ # Define how long the tcp socket stays open, if no data has been received.
203
+ def first_data_timeout(seconds)
204
+ @options[:first_data_timeout] = Integer(seconds)
205
+ end
206
+
207
+ # Work around leaky apps that leave garbage in Thread locals
208
+ # across requests.
209
+ def clean_thread_locals(which=true)
210
+ @options[:clean_thread_locals] = which
211
+ end
212
+
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
223
+ def daemonize(which=true)
224
+ @options[:daemon] = which
225
+ end
226
+
227
+ # When shutting down, drain the accept socket of pending
228
+ # connections and process them. This loops over the accept
229
+ # socket until there are no more read events and then stops
230
+ # looking and waits for the requests to finish.
231
+ def drain_on_shutdown(which=true)
232
+ @options[:drain_on_shutdown] = which
233
+ end
234
+
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'
242
+ def environment(environment)
243
+ @options[:environment] = environment
244
+ end
245
+
246
+ # How long to wait for threads to stop when shutting them
247
+ # down. Defaults to :forever. Specifying :immediately will cause
248
+ # Puma to kill the threads immediately. Otherwise the value
249
+ # is the number of seconds to wait.
250
+ #
251
+ # Puma always waits a few seconds after killing a thread for it to try
252
+ # to finish up it's work, even in :immediately mode.
253
+ def force_shutdown_after(val=:forever)
254
+ i = case val
255
+ when :forever
256
+ -1
257
+ when :immediately
258
+ 0
259
+ else
260
+ Integer(val)
261
+ end
262
+
263
+ @options[:force_shutdown_after] = i
264
+ end
265
+
266
+ # Code to run before doing a restart. This code should
267
+ # close log files, database connections, etc.
268
+ #
269
+ # This can be called multiple times to add code each time.
270
+ #
271
+ # @example
272
+ # on_restart do
273
+ # puts 'On restart...'
274
+ # end
275
+ def on_restart(&block)
276
+ @options[:on_restart] ||= []
277
+ @options[:on_restart] << block
278
+ end
279
+
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.
283
+ #
284
+ # @example
285
+ # restart_command '/u/app/lolcat/bin/restart_puma'
286
+ def restart_command(cmd)
287
+ @options[:restart_cmd] = cmd.to_s
288
+ end
289
+
290
+ # Store the pid of the server in the file at "path".
291
+ #
292
+ # @example
293
+ # pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
294
+ def pidfile(path)
295
+ @options[:pidfile] = path.to_s
296
+ end
297
+
298
+ # Disable request logging, if this isn't used it'll be enabled by default.
299
+ #
300
+ # @example
301
+ # quiet
302
+ def quiet(which=true)
303
+ @options[:log_requests] = !which
304
+ end
305
+
306
+ # Enable request logging
307
+ #
308
+ def log_requests(which=true)
309
+ @options[:log_requests] = which
310
+ end
311
+
312
+ # Show debugging info
313
+ #
314
+ def debug
315
+ @options[:debug] = true
316
+ end
317
+
318
+ # Load +path+ as a rackup file.
319
+ #
320
+ # The default is "config.ru".
321
+ #
322
+ # @example
323
+ # rackup '/u/apps/lolcat/config.ru'
324
+ def rackup(path)
325
+ @options[:rackup] = path.to_s
326
+ end
327
+
328
+ # Run Puma in TCP mode
329
+ #
330
+ def tcp_mode!
331
+ @options[:mode] = :tcp
332
+ end
333
+
334
+ def early_hints(answer=true)
335
+ @options[:early_hints] = answer
336
+ end
337
+
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
345
+ def stdout_redirect(stdout=nil, stderr=nil, append=false)
346
+ @options[:redirect_stdout] = stdout
347
+ @options[:redirect_stderr] = stderr
348
+ @options[:redirect_append] = append
349
+ end
350
+
351
+ def log_formatter(&block)
352
+ @options[:log_formatter] = block
353
+ end
354
+
355
+ # Configure +min+ to be the minimum number of threads to use to answer
356
+ # requests and +max+ the maximum.
357
+ #
358
+ # The default is "0, 16".
359
+ #
360
+ # @example
361
+ # threads 0, 16
362
+ # @example
363
+ # threads 5, 5
364
+ def threads(min, max)
365
+ min = Integer(min)
366
+ max = Integer(max)
367
+ if min > max
368
+ raise "The minimum (#{min}) number of threads must be less than or equal to the max (#{max})"
369
+ end
370
+
371
+ if max < 1
372
+ raise "The maximum number of threads (#{max}) must be greater than 0"
373
+ end
374
+
375
+ @options[:min_threads] = min
376
+ @options[:max_threads] = max
377
+ end
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
+ # }
398
+ def ssl_bind(host, port, opts)
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)
403
+
404
+ if defined?(JRUBY_VERSION)
405
+ keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
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}"
407
+ else
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}"
410
+ end
411
+ end
412
+
413
+ # Use +path+ as the file to store the server info state. This is
414
+ # used by +pumactl+ to query and control the server.
415
+ #
416
+ # @example
417
+ # state_path '/u/apps/lolcat/tmp/pids/puma.state'
418
+ def state_path(path)
419
+ @options[:state] = path.to_s
420
+ end
421
+
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.
426
+ #
427
+ # @note Cluster mode only.
428
+ def workers(count)
429
+ @options[:workers] = count.to_i
430
+ end
431
+
432
+ # Code to run immediately before master process
433
+ # forks workers (once on boot). These hooks can block if necessary
434
+ # to wait for background operations unknown to Puma to finish before
435
+ # the process terminates.
436
+ # This can be used to close any connections to remote servers (database,
437
+ # Redis, ...) that were opened when preloading the code.
438
+ #
439
+ # This can be called multiple times to add several hooks.
440
+ #
441
+ # @note Cluster mode only.
442
+ # @example
443
+ # before_fork do
444
+ # puts "Starting workers..."
445
+ # end
446
+ def before_fork(&block)
447
+ @options[:before_fork] ||= []
448
+ @options[:before_fork] << block
449
+ end
450
+
451
+ # Code to run in a worker when it boots to setup
452
+ # the process before booting the app.
453
+ #
454
+ # This can be called multiple times to add several hooks.
455
+ #
456
+ # @note Cluster mode only.
457
+ # @example
458
+ # on_worker_fork do
459
+ # puts 'Before worker fork...'
460
+ # end
461
+ def on_worker_boot(&block)
462
+ @options[:before_worker_boot] ||= []
463
+ @options[:before_worker_boot] << block
464
+ end
465
+
466
+ # Code to run immediately before a worker shuts
467
+ # down (after it has finished processing HTTP requests). These hooks
468
+ # can block if necessary to wait for background operations unknown
469
+ # to Puma to finish before the process terminates.
470
+ #
471
+ # This can be called multiple times to add several hooks.
472
+ #
473
+ # @note Cluster mode only.
474
+ # @example
475
+ # on_worker_shutdown do
476
+ # puts 'On worker shutdown...'
477
+ # end
478
+ def on_worker_shutdown(&block)
479
+ @options[:before_worker_shutdown] ||= []
480
+ @options[:before_worker_shutdown] << block
481
+ end
482
+
483
+ # Code to run in the master right before a worker is started. The worker's
484
+ # index is passed as an argument.
485
+ #
486
+ # This can be called multiple times to add several hooks.
487
+ #
488
+ # @note Cluster mode only.
489
+ # @example
490
+ # on_worker_fork do
491
+ # puts 'Before worker fork...'
492
+ # end
493
+ def on_worker_fork(&block)
494
+ @options[:before_worker_fork] ||= []
495
+ @options[:before_worker_fork] << block
496
+ end
497
+
498
+ # Code to run in the master after a worker has been started. The worker's
499
+ # index is passed as an argument.
500
+ #
501
+ # This is called everytime a worker is to be started.
502
+ #
503
+ # @note Cluster mode only.
504
+ # @example
505
+ # after_worker_fork do
506
+ # puts 'After worker fork...'
507
+ # end
508
+ def after_worker_fork(&block)
509
+ @options[:after_worker_fork] ||= []
510
+ @options[:after_worker_fork] = block
511
+ end
512
+
513
+ alias_method :after_worker_boot, :after_worker_fork
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
+
529
+ # The directory to operate out of.
530
+ #
531
+ # The default is the current directory.
532
+ #
533
+ # @example
534
+ # directory '/u/apps/lolcat'
535
+ def directory(dir)
536
+ @options[:directory] = dir.to_s
537
+ end
538
+
539
+ # DEPRECATED: The directory to operate out of.
540
+ def worker_directory(dir)
541
+ $stderr.puts "worker_directory is deprecated. Please use `directory`"
542
+ directory dir
543
+ end
544
+
545
+ # Run the app as a raw TCP app instead of an HTTP rack app.
546
+ def tcp_mode
547
+ @options[:mode] = :tcp
548
+ end
549
+
550
+ # Preload the application before starting the workers; this conflicts with
551
+ # phased restart feature. This is off by default.
552
+ #
553
+ # @note Cluster mode only.
554
+ # @example
555
+ # preload_app!
556
+ def preload_app!(answer=true)
557
+ @options[:preload_app] = answer
558
+ end
559
+
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.
562
+ #
563
+ # @example
564
+ # lowlevel_error_handler do |err|
565
+ # [200, {}, ["error page"]]
566
+ # end
567
+ def lowlevel_error_handler(obj=nil, &block)
568
+ obj ||= block
569
+ raise "Provide either a #call'able or a block" unless obj
570
+ @options[:lowlevel_error_handler] = obj
571
+ end
572
+
573
+ # This option is used to allow your app and its gems to be
574
+ # properly reloaded when not using preload.
575
+ #
576
+ # When set, if Puma detects that it's been invoked in the
577
+ # context of Bundler, it will cleanup the environment and
578
+ # re-run itself outside the Bundler environment, but directly
579
+ # using the files that Bundler has setup.
580
+ #
581
+ # This means that Puma is now decoupled from your Bundler
582
+ # context and when each worker loads, it will be loading a
583
+ # new Bundler context and thus can float around as the release
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+
590
+ def prune_bundler(answer=true)
591
+ @options[:prune_bundler] = answer
592
+ end
593
+
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 ''
631
+ def tag(string)
632
+ @options[:tag] = string.to_s
633
+ end
634
+
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
645
+ def worker_timeout(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
654
+ end
655
+
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
663
+ def worker_boot_timeout(timeout)
664
+ @options[:worker_boot_timeout] = Integer(timeout)
665
+ end
666
+
667
+ # Set the timeout for worker shutdown
668
+ #
669
+ # @note Cluster mode only.
670
+ def worker_shutdown_timeout(timeout)
671
+ @options[:worker_shutdown_timeout] = Integer(timeout)
672
+ end
673
+
674
+ # When set to true (the default), workers accept all requests
675
+ # and queue them before passing them to the handlers.
676
+ # When set to false, each worker process accepts exactly as
677
+ # many requests as it is configured to simultaneously handle.
678
+ #
679
+ # Queueing requests generally improves performance. In some
680
+ # cases, such as a single threaded application, it may be
681
+ # better to ensure requests get balanced across workers.
682
+ #
683
+ # Note that setting this to false disables HTTP keepalive and
684
+ # slow clients will occupy a handler thread while the request
685
+ # is being sent. A reverse proxy, such as nginx, can handle
686
+ # slow clients and queue requests before they reach Puma.
687
+ def queue_requests(answer=true)
688
+ @options[:queue_requests] = answer
689
+ end
690
+
691
+ # When a shutdown is requested, the backtraces of all the
692
+ # threads will be written to $stdout. This can help figure
693
+ # out why shutdown is hanging.
694
+ def shutdown_debug(val=true)
695
+ @options[:shutdown_debug] = val
696
+ end
697
+
698
+ # Control how the remote address of the connection is set. This
699
+ # is configurable because to calculate the true socket peer address
700
+ # a kernel syscall is required which for very fast rack handlers
701
+ # slows down the handling significantly.
702
+ #
703
+ # There are 4 possible values:
704
+ #
705
+ # * :socket (the default) - read the peername from the socket using the
706
+ # syscall. This is the normal behavior.
707
+ # * :localhost - set the remote address to "127.0.0.1"
708
+ # * header: http_header - set the remote address to the value of the
709
+ # provided http header. For instance:
710
+ # `set_remote_address header: "X-Real-IP"`.
711
+ # Only the first word (as separated by spaces or comma)
712
+ # is used, allowing headers such as X-Forwarded-For
713
+ # to be used as well.
714
+ # * Any string - this allows you to hardcode remote address to any value
715
+ # you wish. Because Puma never uses this field anyway, it's
716
+ # format is entirely in your hands.
717
+ def set_remote_address(val=:socket)
718
+ case val
719
+ when :socket
720
+ @options[:remote_address] = val
721
+ when :localhost
722
+ @options[:remote_address] = :value
723
+ @options[:remote_address_value] = "127.0.0.1".freeze
724
+ when String
725
+ @options[:remote_address] = :value
726
+ @options[:remote_address_value] = val
727
+ when Hash
728
+ if hdr = val[:header]
729
+ @options[:remote_address] = :header
730
+ @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
731
+ else
732
+ raise "Invalid value for set_remote_address - #{val.inspect}"
733
+ end
734
+ else
735
+ raise "Invalid value for set_remote_address - #{val}"
736
+ end
737
+ end
738
+
739
+ end
740
+ end