puma 4.2.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 +1513 -0
  3. data/LICENSE +26 -0
  4. data/README.md +309 -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 +28 -0
  15. data/docs/restart.md +41 -0
  16. data/docs/signals.md +96 -0
  17. data/docs/systemd.md +290 -0
  18. data/ext/puma_http11/PumaHttp11Service.java +19 -0
  19. data/ext/puma_http11/ext_help.h +15 -0
  20. data/ext/puma_http11/extconf.rb +23 -0
  21. data/ext/puma_http11/http11_parser.c +1044 -0
  22. data/ext/puma_http11/http11_parser.h +65 -0
  23. data/ext/puma_http11/http11_parser.java.rl +161 -0
  24. data/ext/puma_http11/http11_parser.rl +147 -0
  25. data/ext/puma_http11/http11_parser_common.rl +54 -0
  26. data/ext/puma_http11/io_buffer.c +155 -0
  27. data/ext/puma_http11/mini_ssl.c +553 -0
  28. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  29. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +470 -0
  30. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
  31. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +363 -0
  32. data/ext/puma_http11/puma_http11.c +500 -0
  33. data/lib/puma.rb +31 -0
  34. data/lib/puma/accept_nonblock.rb +29 -0
  35. data/lib/puma/app/status.rb +80 -0
  36. data/lib/puma/binder.rb +439 -0
  37. data/lib/puma/cli.rb +239 -0
  38. data/lib/puma/client.rb +494 -0
  39. data/lib/puma/cluster.rb +555 -0
  40. data/lib/puma/commonlogger.rb +108 -0
  41. data/lib/puma/configuration.rb +362 -0
  42. data/lib/puma/const.rb +235 -0
  43. data/lib/puma/control_cli.rb +281 -0
  44. data/lib/puma/convenient.rb +25 -0
  45. data/lib/puma/delegation.rb +13 -0
  46. data/lib/puma/detect.rb +15 -0
  47. data/lib/puma/dsl.rb +738 -0
  48. data/lib/puma/events.rb +156 -0
  49. data/lib/puma/io_buffer.rb +4 -0
  50. data/lib/puma/jruby_restart.rb +84 -0
  51. data/lib/puma/launcher.rb +478 -0
  52. data/lib/puma/minissl.rb +278 -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 +399 -0
  60. data/lib/puma/runner.rb +185 -0
  61. data/lib/puma/server.rb +1033 -0
  62. data/lib/puma/single.rb +124 -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,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/launcher'
4
+ require 'puma/configuration'
5
+
6
+ module Puma
7
+ def self.run(opts={})
8
+ cfg = Puma::Configuration.new do |user_config|
9
+ if port = opts[:port]
10
+ user_config.port port
11
+ end
12
+
13
+ user_config.quiet
14
+
15
+ yield c
16
+ end
17
+
18
+ cfg.clamp
19
+
20
+ events = Puma::Events.null
21
+
22
+ launcher = Puma::Launcher.new cfg, :events => events
23
+ launcher.run
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Puma
4
+ module Delegation
5
+ def forward(what, who)
6
+ module_eval <<-CODE
7
+ def #{what}(*args, &block)
8
+ #{who}.#{what}(*args, &block)
9
+ end
10
+ CODE
11
+ end
12
+ end
13
+ end
@@ -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,738 @@
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')
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
+ # @note This is incompatible with +preload_app!+.
587
+ # @note This is only supported for RubyGems 2.2+
588
+ def prune_bundler(answer=true)
589
+ @options[:prune_bundler] = answer
590
+ end
591
+
592
+ # By default, Puma will raise SignalException when SIGTERM is received. In
593
+ # environments where SIGTERM is something expected, you can suppress these
594
+ # with this option.
595
+ #
596
+ # This can be useful for example in Kubernetes, where rolling restart is
597
+ # guaranteed usually on infrastructure level.
598
+ #
599
+ # @example
600
+ # raise_exception_on_sigterm false
601
+ def raise_exception_on_sigterm(answer=true)
602
+ @options[:raise_exception_on_sigterm] = answer
603
+ end
604
+
605
+ # When using prune_bundler, if extra runtime dependencies need to be loaded to
606
+ # initialize your app, then this setting can be used.
607
+ #
608
+ # Before bundler is pruned, the gem names supplied will be looked up in the bundler
609
+ # context and then loaded again after bundler is pruned.
610
+ # Only applies if prune_bundler is used.
611
+ #
612
+ # @example
613
+ # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
614
+ # @example
615
+ # extra_runtime_dependencies ['puma_worker_killer']
616
+ def extra_runtime_dependencies(answer = [])
617
+ @options[:extra_runtime_dependencies] = Array(answer)
618
+ end
619
+
620
+ # Additional text to display in process listing.
621
+ #
622
+ # If you do not specify a tag, Puma will infer it. If you do not want Puma
623
+ # to add a tag, use an empty string.
624
+ #
625
+ # @example
626
+ # tag 'app name'
627
+ # @example
628
+ # tag ''
629
+ def tag(string)
630
+ @options[:tag] = string.to_s
631
+ end
632
+
633
+ # Verifies that all workers have checked in to the master process within
634
+ # the given timeout. If not the worker process will be restarted. This is
635
+ # not a request timeout, it is to protect against a hung or dead process.
636
+ # Setting this value will not protect against slow requests.
637
+ #
638
+ # The minimum value is 6 seconds, the default value is 60 seconds.
639
+ #
640
+ # @note Cluster mode only.
641
+ # @example
642
+ # worker_timeout 60
643
+ def worker_timeout(timeout)
644
+ timeout = Integer(timeout)
645
+ min = Const::WORKER_CHECK_INTERVAL
646
+
647
+ if timeout <= min
648
+ raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
649
+ end
650
+
651
+ @options[:worker_timeout] = timeout
652
+ end
653
+
654
+ # Change the default worker timeout for booting.
655
+ #
656
+ # If unspecified, this defaults to the value of worker_timeout.
657
+ #
658
+ # @note Cluster mode only.
659
+ # @example:
660
+ # worker_boot_timeout 60
661
+ def worker_boot_timeout(timeout)
662
+ @options[:worker_boot_timeout] = Integer(timeout)
663
+ end
664
+
665
+ # Set the timeout for worker shutdown
666
+ #
667
+ # @note Cluster mode only.
668
+ def worker_shutdown_timeout(timeout)
669
+ @options[:worker_shutdown_timeout] = Integer(timeout)
670
+ end
671
+
672
+ # When set to true (the default), workers accept all requests
673
+ # and queue them before passing them to the handlers.
674
+ # When set to false, each worker process accepts exactly as
675
+ # many requests as it is configured to simultaneously handle.
676
+ #
677
+ # Queueing requests generally improves performance. In some
678
+ # cases, such as a single threaded application, it may be
679
+ # better to ensure requests get balanced across workers.
680
+ #
681
+ # Note that setting this to false disables HTTP keepalive and
682
+ # slow clients will occupy a handler thread while the request
683
+ # is being sent. A reverse proxy, such as nginx, can handle
684
+ # slow clients and queue requests before they reach Puma.
685
+ def queue_requests(answer=true)
686
+ @options[:queue_requests] = answer
687
+ end
688
+
689
+ # When a shutdown is requested, the backtraces of all the
690
+ # threads will be written to $stdout. This can help figure
691
+ # out why shutdown is hanging.
692
+ def shutdown_debug(val=true)
693
+ @options[:shutdown_debug] = val
694
+ end
695
+
696
+ # Control how the remote address of the connection is set. This
697
+ # is configurable because to calculate the true socket peer address
698
+ # a kernel syscall is required which for very fast rack handlers
699
+ # slows down the handling significantly.
700
+ #
701
+ # There are 4 possible values:
702
+ #
703
+ # * :socket (the default) - read the peername from the socket using the
704
+ # syscall. This is the normal behavior.
705
+ # * :localhost - set the remote address to "127.0.0.1"
706
+ # * header: http_header - set the remote address to the value of the
707
+ # provided http header. For instance:
708
+ # `set_remote_address header: "X-Real-IP"`.
709
+ # Only the first word (as separated by spaces or comma)
710
+ # is used, allowing headers such as X-Forwarded-For
711
+ # to be used as well.
712
+ # * Any string - this allows you to hardcode remote address to any value
713
+ # you wish. Because Puma never uses this field anyway, it's
714
+ # format is entirely in your hands.
715
+ def set_remote_address(val=:socket)
716
+ case val
717
+ when :socket
718
+ @options[:remote_address] = val
719
+ when :localhost
720
+ @options[:remote_address] = :value
721
+ @options[:remote_address_value] = "127.0.0.1".freeze
722
+ when String
723
+ @options[:remote_address] = :value
724
+ @options[:remote_address_value] = val
725
+ when Hash
726
+ if hdr = val[:header]
727
+ @options[:remote_address] = :header
728
+ @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
729
+ else
730
+ raise "Invalid value for set_remote_address - #{val.inspect}"
731
+ end
732
+ else
733
+ raise "Invalid value for set_remote_address - #{val}"
734
+ end
735
+ end
736
+
737
+ end
738
+ end