puma 2.0.0.b5 → 5.0.0.beta1

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 (106) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +1598 -0
  3. data/LICENSE +23 -20
  4. data/README.md +222 -62
  5. data/bin/puma-wild +31 -0
  6. data/bin/pumactl +1 -1
  7. data/docs/architecture.md +37 -0
  8. data/docs/deployment.md +113 -0
  9. data/docs/fork_worker.md +31 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +13 -0
  14. data/docs/jungle/rc.d/README.md +74 -0
  15. data/docs/jungle/rc.d/puma +61 -0
  16. data/docs/jungle/rc.d/puma.conf +10 -0
  17. data/docs/jungle/upstart/README.md +61 -0
  18. data/docs/jungle/upstart/puma-manager.conf +31 -0
  19. data/docs/jungle/upstart/puma.conf +69 -0
  20. data/docs/nginx.md +5 -10
  21. data/docs/plugins.md +38 -0
  22. data/docs/restart.md +41 -0
  23. data/docs/signals.md +97 -0
  24. data/docs/systemd.md +228 -0
  25. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  26. data/ext/puma_http11/extconf.rb +23 -2
  27. data/ext/puma_http11/http11_parser.c +301 -482
  28. data/ext/puma_http11/http11_parser.h +13 -11
  29. data/ext/puma_http11/http11_parser.java.rl +26 -42
  30. data/ext/puma_http11/http11_parser.rl +22 -21
  31. data/ext/puma_http11/http11_parser_common.rl +5 -5
  32. data/ext/puma_http11/mini_ssl.c +377 -18
  33. data/ext/puma_http11/org/jruby/puma/Http11.java +108 -107
  34. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +137 -170
  35. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +265 -191
  36. data/ext/puma_http11/puma_http11.c +57 -81
  37. data/lib/puma.rb +25 -4
  38. data/lib/puma/accept_nonblock.rb +7 -1
  39. data/lib/puma/app/status.rb +61 -24
  40. data/lib/puma/binder.rb +212 -78
  41. data/lib/puma/cli.rb +149 -644
  42. data/lib/puma/client.rb +316 -65
  43. data/lib/puma/cluster.rb +659 -0
  44. data/lib/puma/commonlogger.rb +108 -0
  45. data/lib/puma/configuration.rb +279 -180
  46. data/lib/puma/const.rb +126 -39
  47. data/lib/puma/control_cli.rb +183 -96
  48. data/lib/puma/detect.rb +20 -1
  49. data/lib/puma/dsl.rb +776 -0
  50. data/lib/puma/events.rb +91 -23
  51. data/lib/puma/io_buffer.rb +9 -5
  52. data/lib/puma/jruby_restart.rb +9 -5
  53. data/lib/puma/launcher.rb +487 -0
  54. data/lib/puma/minissl.rb +239 -93
  55. data/lib/puma/minissl/context_builder.rb +76 -0
  56. data/lib/puma/null_io.rb +22 -12
  57. data/lib/puma/plugin.rb +111 -0
  58. data/lib/puma/plugin/tmp_restart.rb +36 -0
  59. data/lib/puma/rack/builder.rb +297 -0
  60. data/lib/puma/rack/urlmap.rb +93 -0
  61. data/lib/puma/rack_default.rb +9 -0
  62. data/lib/puma/reactor.rb +290 -43
  63. data/lib/puma/runner.rb +163 -0
  64. data/lib/puma/server.rb +493 -126
  65. data/lib/puma/single.rb +66 -0
  66. data/lib/puma/state_file.rb +34 -0
  67. data/lib/puma/thread_pool.rb +228 -47
  68. data/lib/puma/util.rb +115 -0
  69. data/lib/rack/handler/puma.rb +78 -31
  70. data/tools/Dockerfile +16 -0
  71. data/tools/trickletest.rb +44 -0
  72. metadata +60 -155
  73. data/COPYING +0 -55
  74. data/Gemfile +0 -8
  75. data/History.txt +0 -196
  76. data/Manifest.txt +0 -56
  77. data/Rakefile +0 -121
  78. data/TODO +0 -5
  79. data/docs/config.md +0 -0
  80. data/ext/puma_http11/io_buffer.c +0 -154
  81. data/lib/puma/capistrano.rb +0 -26
  82. data/lib/puma/compat.rb +0 -11
  83. data/lib/puma/daemon_ext.rb +0 -20
  84. data/lib/puma/delegation.rb +0 -11
  85. data/lib/puma/java_io_buffer.rb +0 -45
  86. data/lib/puma/rack_patch.rb +0 -25
  87. data/puma.gemspec +0 -45
  88. data/test/test_app_status.rb +0 -88
  89. data/test/test_cli.rb +0 -171
  90. data/test/test_config.rb +0 -16
  91. data/test/test_http10.rb +0 -27
  92. data/test/test_http11.rb +0 -126
  93. data/test/test_integration.rb +0 -150
  94. data/test/test_iobuffer.rb +0 -38
  95. data/test/test_minissl.rb +0 -22
  96. data/test/test_null_io.rb +0 -31
  97. data/test/test_persistent.rb +0 -238
  98. data/test/test_puma_server.rb +0 -128
  99. data/test/test_rack_handler.rb +0 -10
  100. data/test/test_rack_server.rb +0 -141
  101. data/test/test_thread_pool.rb +0 -146
  102. data/test/test_unix_socket.rb +0 -39
  103. data/test/test_ws.rb +0 -89
  104. data/tools/jungle/README.md +0 -54
  105. data/tools/jungle/puma +0 -332
  106. data/tools/jungle/run-puma +0 -3
@@ -1,4 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Puma
2
4
  IS_JRUBY = defined?(JRUBY_VERSION)
3
- end
4
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
+
16
+ def self.mri?
17
+ RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?
18
+ end
19
+
20
+ def self.forkable?
21
+ ::Process.respond_to?(:fork)
22
+ end
23
+ end
@@ -0,0 +1,776 @@
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
+ # When shutting down, drain the accept socket of pending
214
+ # connections and process them. This loops over the accept
215
+ # socket until there are no more read events and then stops
216
+ # looking and waits for the requests to finish.
217
+ def drain_on_shutdown(which=true)
218
+ @options[:drain_on_shutdown] = which
219
+ end
220
+
221
+ # Set the environment in which the rack's app will run. The value must be
222
+ # a string.
223
+ #
224
+ # The default is "development".
225
+ #
226
+ # @example
227
+ # environment 'production'
228
+ def environment(environment)
229
+ @options[:environment] = environment
230
+ end
231
+
232
+ # How long to wait for threads to stop when shutting them
233
+ # down. Defaults to :forever. Specifying :immediately will cause
234
+ # Puma to kill the threads immediately. Otherwise the value
235
+ # is the number of seconds to wait.
236
+ #
237
+ # Puma always waits a few seconds after killing a thread for it to try
238
+ # to finish up it's work, even in :immediately mode.
239
+ def force_shutdown_after(val=:forever)
240
+ i = case val
241
+ when :forever
242
+ -1
243
+ when :immediately
244
+ 0
245
+ else
246
+ Float(val)
247
+ end
248
+
249
+ @options[:force_shutdown_after] = i
250
+ end
251
+
252
+ # Code to run before doing a restart. This code should
253
+ # close log files, database connections, etc.
254
+ #
255
+ # This can be called multiple times to add code each time.
256
+ #
257
+ # @example
258
+ # on_restart do
259
+ # puts 'On restart...'
260
+ # end
261
+ def on_restart(&block)
262
+ @options[:on_restart] ||= []
263
+ @options[:on_restart] << block
264
+ end
265
+
266
+ # Command to use to restart Puma. This should be just how to
267
+ # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
268
+ # to Puma, as those are the same as the original process.
269
+ #
270
+ # @example
271
+ # restart_command '/u/app/lolcat/bin/restart_puma'
272
+ def restart_command(cmd)
273
+ @options[:restart_cmd] = cmd.to_s
274
+ end
275
+
276
+ # Store the pid of the server in the file at "path".
277
+ #
278
+ # @example
279
+ # pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
280
+ def pidfile(path)
281
+ @options[:pidfile] = path.to_s
282
+ end
283
+
284
+ # Disable request logging, if this isn't used it'll be enabled by default.
285
+ #
286
+ # @example
287
+ # quiet
288
+ def quiet(which=true)
289
+ @options[:log_requests] = !which
290
+ end
291
+
292
+ # Enable request logging
293
+ #
294
+ def log_requests(which=true)
295
+ @options[:log_requests] = which
296
+ end
297
+
298
+ # Show debugging info
299
+ #
300
+ def debug
301
+ @options[:debug] = true
302
+ end
303
+
304
+ # Load +path+ as a rackup file.
305
+ #
306
+ # The default is "config.ru".
307
+ #
308
+ # @example
309
+ # rackup '/u/apps/lolcat/config.ru'
310
+ def rackup(path)
311
+ @options[:rackup] ||= path.to_s
312
+ end
313
+
314
+ def early_hints(answer=true)
315
+ @options[:early_hints] = answer
316
+ end
317
+
318
+ # Redirect STDOUT and STDERR to files specified. The +append+ parameter
319
+ # specifies whether the output is appended, the default is +false+.
320
+ #
321
+ # @example
322
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
323
+ # @example
324
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
325
+ def stdout_redirect(stdout=nil, stderr=nil, append=false)
326
+ @options[:redirect_stdout] = stdout
327
+ @options[:redirect_stderr] = stderr
328
+ @options[:redirect_append] = append
329
+ end
330
+
331
+ def log_formatter(&block)
332
+ @options[:log_formatter] = block
333
+ end
334
+
335
+ # Configure +min+ to be the minimum number of threads to use to answer
336
+ # requests and +max+ the maximum.
337
+ #
338
+ # The default is "0, 16".
339
+ #
340
+ # @example
341
+ # threads 0, 16
342
+ # @example
343
+ # threads 5, 5
344
+ def threads(min, max)
345
+ min = Integer(min)
346
+ max = Integer(max)
347
+ if min > max
348
+ raise "The minimum (#{min}) number of threads must be less than or equal to the max (#{max})"
349
+ end
350
+
351
+ if max < 1
352
+ raise "The maximum number of threads (#{max}) must be greater than 0"
353
+ end
354
+
355
+ @options[:min_threads] = min
356
+ @options[:max_threads] = max
357
+ end
358
+
359
+ # Instead of "bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'" you
360
+ # can also use the "ssl_bind" option.
361
+ #
362
+ # @example
363
+ # ssl_bind '127.0.0.1', '9292', {
364
+ # cert: path_to_cert,
365
+ # key: path_to_key,
366
+ # ssl_cipher_filter: cipher_filter, # optional
367
+ # verify_mode: verify_mode, # default 'none'
368
+ # }
369
+ # @example For JRuby additional keys are required: keystore & keystore_pass.
370
+ # ssl_bind '127.0.0.1', '9292', {
371
+ # cert: path_to_cert,
372
+ # key: path_to_key,
373
+ # ssl_cipher_filter: cipher_filter, # optional
374
+ # verify_mode: verify_mode, # default 'none'
375
+ # keystore: path_to_keystore,
376
+ # keystore_pass: password
377
+ # }
378
+ def ssl_bind(host, port, opts)
379
+ verify = opts.fetch(:verify_mode, 'none').to_s
380
+ no_tlsv1 = opts.fetch(:no_tlsv1, 'false')
381
+ no_tlsv1_1 = opts.fetch(:no_tlsv1_1, 'false')
382
+ ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
383
+
384
+ if defined?(JRUBY_VERSION)
385
+ keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
386
+ 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}"
387
+ else
388
+ ssl_cipher_filter = "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" if opts[:ssl_cipher_filter]
389
+ 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}"
390
+ end
391
+ end
392
+
393
+ # Use +path+ as the file to store the server info state. This is
394
+ # used by +pumactl+ to query and control the server.
395
+ #
396
+ # @example
397
+ # state_path '/u/apps/lolcat/tmp/pids/puma.state'
398
+ def state_path(path)
399
+ @options[:state] = path.to_s
400
+ end
401
+
402
+ # Use +permission+ to restrict permissions for the state file.
403
+ #
404
+ # @example
405
+ # state_permission 0600
406
+ def state_permission(permission)
407
+ @options[:state_permission] = permission
408
+ end
409
+
410
+ # How many worker processes to run. Typically this is set to
411
+ # the number of available cores.
412
+ #
413
+ # The default is 0.
414
+ #
415
+ # @note Cluster mode only.
416
+ def workers(count)
417
+ @options[:workers] = count.to_i
418
+ end
419
+
420
+ # Code to run immediately before master process
421
+ # forks workers (once on boot). These hooks can block if necessary
422
+ # to wait for background operations unknown to Puma to finish before
423
+ # the process terminates.
424
+ # This can be used to close any connections to remote servers (database,
425
+ # Redis, ...) that were opened when preloading the code.
426
+ #
427
+ # This can be called multiple times to add several hooks.
428
+ #
429
+ # @note Cluster mode only.
430
+ # @example
431
+ # before_fork do
432
+ # puts "Starting workers..."
433
+ # end
434
+ def before_fork(&block)
435
+ @options[:before_fork] ||= []
436
+ @options[:before_fork] << block
437
+ end
438
+
439
+ # Code to run in a worker when it boots to setup
440
+ # the process before booting the app.
441
+ #
442
+ # This can be called multiple times to add several hooks.
443
+ #
444
+ # @note Cluster mode only.
445
+ # @example
446
+ # on_worker_fork do
447
+ # puts 'Before worker fork...'
448
+ # end
449
+ def on_worker_boot(&block)
450
+ @options[:before_worker_boot] ||= []
451
+ @options[:before_worker_boot] << block
452
+ end
453
+
454
+ # Code to run immediately before a worker shuts
455
+ # down (after it has finished processing HTTP requests). These hooks
456
+ # can block if necessary to wait for background operations unknown
457
+ # to Puma to finish before the process terminates.
458
+ #
459
+ # This can be called multiple times to add several hooks.
460
+ #
461
+ # @note Cluster mode only.
462
+ # @example
463
+ # on_worker_shutdown do
464
+ # puts 'On worker shutdown...'
465
+ # end
466
+ def on_worker_shutdown(&block)
467
+ @options[:before_worker_shutdown] ||= []
468
+ @options[:before_worker_shutdown] << block
469
+ end
470
+
471
+ # Code to run in the master right before a worker is started. The worker's
472
+ # index is passed as an argument.
473
+ #
474
+ # This can be called multiple times to add several hooks.
475
+ #
476
+ # @note Cluster mode only.
477
+ # @example
478
+ # on_worker_fork do
479
+ # puts 'Before worker fork...'
480
+ # end
481
+ def on_worker_fork(&block)
482
+ @options[:before_worker_fork] ||= []
483
+ @options[:before_worker_fork] << block
484
+ end
485
+
486
+ # Code to run in the master after a worker has been started. The worker's
487
+ # index is passed as an argument.
488
+ #
489
+ # This is called everytime a worker is to be started.
490
+ #
491
+ # @note Cluster mode only.
492
+ # @example
493
+ # after_worker_fork do
494
+ # puts 'After worker fork...'
495
+ # end
496
+ def after_worker_fork(&block)
497
+ @options[:after_worker_fork] ||= []
498
+ @options[:after_worker_fork] = block
499
+ end
500
+
501
+ alias_method :after_worker_boot, :after_worker_fork
502
+
503
+ # When `fork_worker` is enabled, code to run in Worker 0
504
+ # before all other workers are re-forked from this process,
505
+ # after the server has temporarily stopped serving requests
506
+ # (once per complete refork cycle).
507
+ #
508
+ # This can be used to trigger extra garbage-collection to maximize
509
+ # copy-on-write efficiency, or close any connections to remote servers
510
+ # (database, Redis, ...) that were opened while the server was running.
511
+ #
512
+ # This can be called multiple times to add several hooks.
513
+ #
514
+ # @note Cluster mode with `fork_worker` enabled only.
515
+ # @example
516
+ # on_refork do
517
+ # 3.times {GC.start}
518
+ # end
519
+
520
+ def on_refork(&block)
521
+ @options[:before_refork] ||= []
522
+ @options[:before_refork] << block
523
+ end
524
+
525
+ # Code to run out-of-band when the worker is idle.
526
+ # These hooks run immediately after a request has finished
527
+ # processing and there are no busy threads on the worker.
528
+ # The worker doesn't accept new requests until this code finishes.
529
+ #
530
+ # This hook is useful for running out-of-band garbage collection
531
+ # or scheduling asynchronous tasks to execute after a response.
532
+ #
533
+ # This can be called multiple times to add several hooks.
534
+ def out_of_band(&block)
535
+ @options[:out_of_band] ||= []
536
+ @options[:out_of_band] << block
537
+ end
538
+
539
+ # The directory to operate out of.
540
+ #
541
+ # The default is the current directory.
542
+ #
543
+ # @example
544
+ # directory '/u/apps/lolcat'
545
+ def directory(dir)
546
+ @options[:directory] = dir.to_s
547
+ end
548
+
549
+ # Preload the application before starting the workers; this conflicts with
550
+ # phased restart feature. This is off by default.
551
+ #
552
+ # @note Cluster mode only.
553
+ # @example
554
+ # preload_app!
555
+ def preload_app!(answer=true)
556
+ @options[:preload_app] = answer
557
+ end
558
+
559
+ # Use +obj+ or +block+ as the low level error handler. This allows the
560
+ # configuration file to change the default error on the server.
561
+ #
562
+ # @example
563
+ # lowlevel_error_handler do |err|
564
+ # [200, {}, ["error page"]]
565
+ # end
566
+ def lowlevel_error_handler(obj=nil, &block)
567
+ obj ||= block
568
+ raise "Provide either a #call'able or a block" unless obj
569
+ @options[:lowlevel_error_handler] = obj
570
+ end
571
+
572
+ # This option is used to allow your app and its gems to be
573
+ # properly reloaded when not using preload.
574
+ #
575
+ # When set, if Puma detects that it's been invoked in the
576
+ # context of Bundler, it will cleanup the environment and
577
+ # re-run itself outside the Bundler environment, but directly
578
+ # using the files that Bundler has setup.
579
+ #
580
+ # This means that Puma is now decoupled from your Bundler
581
+ # context and when each worker loads, it will be loading a
582
+ # new Bundler context and thus can float around as the release
583
+ # dictates.
584
+ #
585
+ # See also: extra_runtime_dependencies
586
+ #
587
+ # @note This is incompatible with +preload_app!+.
588
+ # @note This is only supported for RubyGems 2.2+
589
+ def prune_bundler(answer=true)
590
+ @options[:prune_bundler] = answer
591
+ end
592
+
593
+ # By default, Puma will raise SignalException when SIGTERM is received. In
594
+ # environments where SIGTERM is something expected, you can suppress these
595
+ # with this option.
596
+ #
597
+ # This can be useful for example in Kubernetes, where rolling restart is
598
+ # guaranteed usually on infrastructure level.
599
+ #
600
+ # @example
601
+ # raise_exception_on_sigterm false
602
+ def raise_exception_on_sigterm(answer=true)
603
+ @options[:raise_exception_on_sigterm] = answer
604
+ end
605
+
606
+ # When using prune_bundler, if extra runtime dependencies need to be loaded to
607
+ # initialize your app, then this setting can be used. This includes any Puma plugins.
608
+ #
609
+ # Before bundler is pruned, the gem names supplied will be looked up in the bundler
610
+ # context and then loaded again after bundler is pruned.
611
+ # Only applies if prune_bundler is used.
612
+ #
613
+ # @example
614
+ # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
615
+ # @example
616
+ # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
617
+ def extra_runtime_dependencies(answer = [])
618
+ @options[:extra_runtime_dependencies] = Array(answer)
619
+ end
620
+
621
+ # Additional text to display in process listing.
622
+ #
623
+ # If you do not specify a tag, Puma will infer it. If you do not want Puma
624
+ # to add a tag, use an empty string.
625
+ #
626
+ # @example
627
+ # tag 'app name'
628
+ # @example
629
+ # tag ''
630
+ def tag(string)
631
+ @options[:tag] = string.to_s
632
+ end
633
+
634
+ # Verifies that all workers have checked in to the master process within
635
+ # the given timeout. If not the worker process will be restarted. This is
636
+ # not a request timeout, it is to protect against a hung or dead process.
637
+ # Setting this value will not protect against slow requests.
638
+ #
639
+ # The minimum value is 6 seconds, the default value is 60 seconds.
640
+ #
641
+ # @note Cluster mode only.
642
+ # @example
643
+ # worker_timeout 60
644
+ def worker_timeout(timeout)
645
+ timeout = Integer(timeout)
646
+ min = Const::WORKER_CHECK_INTERVAL
647
+
648
+ if timeout <= min
649
+ raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
650
+ end
651
+
652
+ @options[:worker_timeout] = timeout
653
+ end
654
+
655
+ # Change the default worker timeout for booting.
656
+ #
657
+ # If unspecified, this defaults to the value of worker_timeout.
658
+ #
659
+ # @note Cluster mode only.
660
+ # @example:
661
+ # worker_boot_timeout 60
662
+ def worker_boot_timeout(timeout)
663
+ @options[:worker_boot_timeout] = Integer(timeout)
664
+ end
665
+
666
+ # Set the timeout for worker shutdown
667
+ #
668
+ # @note Cluster mode only.
669
+ def worker_shutdown_timeout(timeout)
670
+ @options[:worker_shutdown_timeout] = Integer(timeout)
671
+ end
672
+
673
+ # When set to true (the default), workers accept all requests
674
+ # and queue them before passing them to the handlers.
675
+ # When set to false, each worker process accepts exactly as
676
+ # many requests as it is configured to simultaneously handle.
677
+ #
678
+ # Queueing requests generally improves performance. In some
679
+ # cases, such as a single threaded application, it may be
680
+ # better to ensure requests get balanced across workers.
681
+ #
682
+ # Note that setting this to false disables HTTP keepalive and
683
+ # slow clients will occupy a handler thread while the request
684
+ # is being sent. A reverse proxy, such as nginx, can handle
685
+ # slow clients and queue requests before they reach Puma.
686
+ def queue_requests(answer=true)
687
+ @options[:queue_requests] = answer
688
+ end
689
+
690
+ # When a shutdown is requested, the backtraces of all the
691
+ # threads will be written to $stdout. This can help figure
692
+ # out why shutdown is hanging.
693
+ def shutdown_debug(val=true)
694
+ @options[:shutdown_debug] = val
695
+ end
696
+
697
+
698
+ # Attempts to route traffic to less-busy workers by causing them to delay
699
+ # listening on the socket, allowing workers which are not processing any
700
+ # requests to pick up new requests first.
701
+ #
702
+ # Only works on MRI. For all other interpreters, this setting does nothing.
703
+ def wait_for_less_busy_worker(val=0.005)
704
+ @options[:wait_for_less_busy_worker] = val.to_f
705
+ end
706
+
707
+ # Control how the remote address of the connection is set. This
708
+ # is configurable because to calculate the true socket peer address
709
+ # a kernel syscall is required which for very fast rack handlers
710
+ # slows down the handling significantly.
711
+ #
712
+ # There are 4 possible values:
713
+ #
714
+ # * :socket (the default) - read the peername from the socket using the
715
+ # syscall. This is the normal behavior.
716
+ # * :localhost - set the remote address to "127.0.0.1"
717
+ # * header: http_header - set the remote address to the value of the
718
+ # provided http header. For instance:
719
+ # `set_remote_address header: "X-Real-IP"`.
720
+ # Only the first word (as separated by spaces or comma)
721
+ # is used, allowing headers such as X-Forwarded-For
722
+ # to be used as well.
723
+ # * Any string - this allows you to hardcode remote address to any value
724
+ # you wish. Because Puma never uses this field anyway, it's
725
+ # format is entirely in your hands.
726
+ def set_remote_address(val=:socket)
727
+ case val
728
+ when :socket
729
+ @options[:remote_address] = val
730
+ when :localhost
731
+ @options[:remote_address] = :value
732
+ @options[:remote_address_value] = "127.0.0.1".freeze
733
+ when String
734
+ @options[:remote_address] = :value
735
+ @options[:remote_address_value] = val
736
+ when Hash
737
+ if hdr = val[:header]
738
+ @options[:remote_address] = :header
739
+ @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
740
+ else
741
+ raise "Invalid value for set_remote_address - #{val.inspect}"
742
+ end
743
+ else
744
+ raise "Invalid value for set_remote_address - #{val}"
745
+ end
746
+ end
747
+
748
+ # When enabled, workers will be forked from worker 0 instead of from the master process.
749
+ # This option is similar to `preload_app` because the app is preloaded before forking,
750
+ # but it is compatible with phased restart.
751
+ #
752
+ # This option also enables the `refork` command (SIGURG), which optimizes copy-on-write performance
753
+ # in a running app.
754
+ #
755
+ # A refork will automatically trigger once after the specified number of requests
756
+ # (default 1000), or pass 0 to disable auto refork.
757
+ #
758
+ # @note Cluster mode only.
759
+ def fork_worker(after_requests=1000)
760
+ @options[:fork_worker] = Integer(after_requests)
761
+ end
762
+
763
+ # When enabled, Puma will GC 4 times before forking workers.
764
+ # If available (Ruby 2.7+), we will also call GC.compact.
765
+ # Not recommended for non-MRI Rubies.
766
+ #
767
+ # Based on the work of Koichi Sasada and Aaron Patterson, this option may
768
+ # decrease memory utilization of preload-enabled cluster-mode Pumas. It will
769
+ # also increase time to boot and fork. See your logs for details on how much
770
+ # time this adds to your boot process. For most apps, it will be less than one
771
+ # second.
772
+ def nakayoshi_fork(enabled=false)
773
+ @options[:nakayoshi_fork] = enabled
774
+ end
775
+ end
776
+ end