jun-puma 1.0.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +2897 -0
  3. data/LICENSE +29 -0
  4. data/README.md +475 -0
  5. data/bin/puma +10 -0
  6. data/bin/puma-wild +25 -0
  7. data/bin/pumactl +12 -0
  8. data/docs/architecture.md +74 -0
  9. data/docs/compile_options.md +55 -0
  10. data/docs/deployment.md +102 -0
  11. data/docs/fork_worker.md +35 -0
  12. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  13. data/docs/images/puma-connection-flow.png +0 -0
  14. data/docs/images/puma-general-arch.png +0 -0
  15. data/docs/jungle/README.md +9 -0
  16. data/docs/jungle/rc.d/README.md +74 -0
  17. data/docs/jungle/rc.d/puma +61 -0
  18. data/docs/jungle/rc.d/puma.conf +10 -0
  19. data/docs/kubernetes.md +78 -0
  20. data/docs/nginx.md +80 -0
  21. data/docs/plugins.md +38 -0
  22. data/docs/rails_dev_mode.md +28 -0
  23. data/docs/restart.md +65 -0
  24. data/docs/signals.md +98 -0
  25. data/docs/stats.md +142 -0
  26. data/docs/systemd.md +253 -0
  27. data/docs/testing_benchmarks_local_files.md +150 -0
  28. data/docs/testing_test_rackup_ci_files.md +36 -0
  29. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  30. data/ext/puma_http11/ext_help.h +15 -0
  31. data/ext/puma_http11/extconf.rb +80 -0
  32. data/ext/puma_http11/http11_parser.c +1057 -0
  33. data/ext/puma_http11/http11_parser.h +65 -0
  34. data/ext/puma_http11/http11_parser.java.rl +145 -0
  35. data/ext/puma_http11/http11_parser.rl +149 -0
  36. data/ext/puma_http11/http11_parser_common.rl +54 -0
  37. data/ext/puma_http11/mini_ssl.c +842 -0
  38. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  39. data/ext/puma_http11/org/jruby/puma/Http11.java +228 -0
  40. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +455 -0
  41. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +509 -0
  42. data/ext/puma_http11/puma_http11.c +495 -0
  43. data/lib/puma/app/status.rb +96 -0
  44. data/lib/puma/binder.rb +502 -0
  45. data/lib/puma/cli.rb +247 -0
  46. data/lib/puma/client.rb +682 -0
  47. data/lib/puma/cluster/worker.rb +180 -0
  48. data/lib/puma/cluster/worker_handle.rb +96 -0
  49. data/lib/puma/cluster.rb +616 -0
  50. data/lib/puma/commonlogger.rb +115 -0
  51. data/lib/puma/configuration.rb +390 -0
  52. data/lib/puma/const.rb +307 -0
  53. data/lib/puma/control_cli.rb +316 -0
  54. data/lib/puma/detect.rb +45 -0
  55. data/lib/puma/dsl.rb +1425 -0
  56. data/lib/puma/error_logger.rb +113 -0
  57. data/lib/puma/events.rb +57 -0
  58. data/lib/puma/io_buffer.rb +46 -0
  59. data/lib/puma/jruby_restart.rb +11 -0
  60. data/lib/puma/json_serialization.rb +96 -0
  61. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  62. data/lib/puma/launcher.rb +488 -0
  63. data/lib/puma/log_writer.rb +147 -0
  64. data/lib/puma/minissl/context_builder.rb +96 -0
  65. data/lib/puma/minissl.rb +459 -0
  66. data/lib/puma/null_io.rb +84 -0
  67. data/lib/puma/plugin/systemd.rb +90 -0
  68. data/lib/puma/plugin/tmp_restart.rb +36 -0
  69. data/lib/puma/plugin.rb +111 -0
  70. data/lib/puma/puma_http11.jar +0 -0
  71. data/lib/puma/rack/builder.rb +297 -0
  72. data/lib/puma/rack/urlmap.rb +93 -0
  73. data/lib/puma/rack_default.rb +24 -0
  74. data/lib/puma/reactor.rb +125 -0
  75. data/lib/puma/request.rb +688 -0
  76. data/lib/puma/runner.rb +213 -0
  77. data/lib/puma/sd_notify.rb +149 -0
  78. data/lib/puma/server.rb +680 -0
  79. data/lib/puma/single.rb +69 -0
  80. data/lib/puma/state_file.rb +68 -0
  81. data/lib/puma/thread_pool.rb +434 -0
  82. data/lib/puma/util.rb +141 -0
  83. data/lib/puma.rb +78 -0
  84. data/lib/rack/handler/puma.rb +144 -0
  85. data/tools/Dockerfile +16 -0
  86. data/tools/trickletest.rb +44 -0
  87. metadata +153 -0
data/lib/puma/dsl.rb ADDED
@@ -0,0 +1,1425 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'const'
4
+ require_relative 'util'
5
+
6
+ module Puma
7
+ # The methods that are available for use inside the configuration file.
8
+ # These same methods are used in Puma cli and the rack handler
9
+ # internally.
10
+ #
11
+ # Used manually (via CLI class):
12
+ #
13
+ # config = Configuration.new({}) do |user_config|
14
+ # user_config.port 3001
15
+ # end
16
+ # config.load
17
+ #
18
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3001"
19
+ #
20
+ # Used to load file:
21
+ #
22
+ # $ cat puma_config.rb
23
+ # port 3002
24
+ #
25
+ # Resulting configuration:
26
+ #
27
+ # config = Configuration.new(config_file: "puma_config.rb")
28
+ # config.load
29
+ #
30
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3002"
31
+ #
32
+ # You can also find many examples being used by the test suite in
33
+ # +test/config+.
34
+ #
35
+ # Puma v6 adds the option to specify a key name (String or Symbol) to the
36
+ # hooks that run inside the forked workers. All the hooks run inside the
37
+ # {Puma::Cluster::Worker#run} method.
38
+ #
39
+ # Previously, the worker index and the LogWriter instance were passed to the
40
+ # hook blocks/procs. If a key name is specified, a hash is passed as the last
41
+ # parameter. This allows storage of data, typically objects that are created
42
+ # before the worker that need to be passed to the hook when the worker is shutdown.
43
+ #
44
+ # The following hooks have been updated:
45
+ #
46
+ # | DSL Method | Options Key | Fork Block Location |
47
+ # | on_worker_boot | :before_worker_boot | inside, before |
48
+ # | on_worker_shutdown | :before_worker_shutdown | inside, after |
49
+ # | on_refork | :before_refork | inside |
50
+ #
51
+ class DSL
52
+ ON_WORKER_KEY = [String, Symbol].freeze
53
+
54
+ # Convenience method so logic can be used in CI.
55
+ #
56
+ # @see ssl_bind
57
+ #
58
+ def self.ssl_bind_str(host, port, opts)
59
+ verify = opts.fetch(:verify_mode, 'none').to_s
60
+
61
+ tls_str =
62
+ if opts[:no_tlsv1_1] then '&no_tlsv1_1=true'
63
+ elsif opts[:no_tlsv1] then '&no_tlsv1=true'
64
+ else ''
65
+ end
66
+
67
+ ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
68
+
69
+ low_latency_str = opts.key?(:low_latency) ? "&low_latency=#{opts[:low_latency]}" : ''
70
+ backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
71
+
72
+ if defined?(JRUBY_VERSION)
73
+ cipher_suites = opts[:ssl_cipher_list] ? "&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil # old name
74
+ cipher_suites = "#{cipher_suites}&cipher_suites=#{opts[:cipher_suites]}" if opts[:cipher_suites]
75
+ protocols = opts[:protocols] ? "&protocols=#{opts[:protocols]}" : nil
76
+
77
+ keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
78
+ keystore_additions = "#{keystore_additions}&keystore-type=#{opts[:keystore_type]}" if opts[:keystore_type]
79
+ if opts[:truststore]
80
+ truststore_additions = "&truststore=#{opts[:truststore]}"
81
+ truststore_additions = "#{truststore_additions}&truststore-pass=#{opts[:truststore_pass]}" if opts[:truststore_pass]
82
+ truststore_additions = "#{truststore_additions}&truststore-type=#{opts[:truststore_type]}" if opts[:truststore_type]
83
+ end
84
+
85
+ "ssl://#{host}:#{port}?#{keystore_additions}#{truststore_additions}#{cipher_suites}#{protocols}" \
86
+ "&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
87
+ else
88
+ ssl_cipher_filter = opts[:ssl_cipher_filter] ? "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
89
+ ssl_ciphersuites = opts[:ssl_ciphersuites] ? "&ssl_ciphersuites=#{opts[:ssl_ciphersuites]}" : nil
90
+ v_flags = (ary = opts[:verification_flags]) ? "&verification_flags=#{Array(ary).join ','}" : nil
91
+
92
+ cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(cert)}" : nil
93
+ key_flags = (key = opts[:key]) ? "&key=#{Puma::Util.escape(key)}" : nil
94
+ password_flags = (password_command = opts[:key_password_command]) ? "&key_password_command=#{Puma::Util.escape(password_command)}" : nil
95
+
96
+ reuse_flag =
97
+ if (reuse = opts[:reuse])
98
+ if reuse == true
99
+ '&reuse=dflt'
100
+ elsif reuse.is_a?(Hash) && (reuse.key?(:size) || reuse.key?(:timeout))
101
+ val = +''
102
+ if (size = reuse[:size]) && Integer === size
103
+ val << size.to_s
104
+ end
105
+ if (timeout = reuse[:timeout]) && Integer === timeout
106
+ val << ",#{timeout}"
107
+ end
108
+ if val.empty?
109
+ nil
110
+ else
111
+ "&reuse=#{val}"
112
+ end
113
+ else
114
+ nil
115
+ end
116
+ else
117
+ nil
118
+ end
119
+
120
+ "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{password_flags}#{ssl_cipher_filter}#{ssl_ciphersuites}" \
121
+ "#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}#{low_latency_str}"
122
+ end
123
+ end
124
+
125
+ def initialize(options, config)
126
+ @config = config
127
+ @options = options
128
+
129
+ @plugins = []
130
+ end
131
+
132
+ def _load_from(path)
133
+ if path
134
+ @path = path
135
+ instance_eval(File.read(path), path, 1)
136
+ end
137
+ ensure
138
+ _offer_plugins
139
+ end
140
+
141
+ def _offer_plugins
142
+ @plugins.each do |o|
143
+ if o.respond_to? :config
144
+ @options.shift
145
+ o.config self
146
+ end
147
+ end
148
+
149
+ @plugins.clear
150
+ end
151
+
152
+ def set_default_host(host)
153
+ @options[:default_host] = host
154
+ end
155
+
156
+ def default_host
157
+ @options[:default_host] || Configuration::DEFAULTS[:tcp_host]
158
+ end
159
+
160
+ def inject(&blk)
161
+ instance_eval(&blk)
162
+ end
163
+
164
+ def get(key,default=nil)
165
+ @options[key.to_sym] || default
166
+ end
167
+
168
+ # Load the named plugin for use by this configuration.
169
+ #
170
+ # @example
171
+ # plugin :tmp_restart
172
+ #
173
+ def plugin(name)
174
+ @plugins << @config.load_plugin(name)
175
+ end
176
+
177
+ # Use an object or block as the rack application. This allows the
178
+ # configuration file to be the application itself.
179
+ #
180
+ # @example
181
+ # app do |env|
182
+ # body = 'Hello, World!'
183
+ #
184
+ # [
185
+ # 200,
186
+ # {
187
+ # 'Content-Type' => 'text/plain',
188
+ # 'Content-Length' => body.length.to_s
189
+ # },
190
+ # [body]
191
+ # ]
192
+ # end
193
+ #
194
+ # @see Puma::Configuration#app
195
+ #
196
+ def app(obj=nil, &block)
197
+ obj ||= block
198
+
199
+ raise "Provide either a #call'able or a block" unless obj
200
+
201
+ @options[:app] = obj
202
+ end
203
+
204
+ # Start the Puma control rack application on +url+. This application can
205
+ # be communicated with to control the main server. Additionally, you can
206
+ # provide an authentication token, so all requests to the control server
207
+ # will need to include that token as a query parameter. This allows for
208
+ # simple authentication.
209
+ #
210
+ # Check out {Puma::App::Status} to see what the app has available.
211
+ #
212
+ # @example
213
+ # activate_control_app 'unix:///var/run/pumactl.sock'
214
+ # @example
215
+ # activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
216
+ # @example
217
+ # activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
218
+ #
219
+ def activate_control_app(url="auto", opts={})
220
+ if url == "auto"
221
+ path = Configuration.temp_path
222
+ @options[:control_url] = "unix://#{path}"
223
+ @options[:control_url_temp] = path
224
+ else
225
+ @options[:control_url] = url
226
+ end
227
+
228
+ if opts[:no_token]
229
+ # We need to use 'none' rather than :none because this value will be
230
+ # passed on to an instance of OptionParser, which doesn't support
231
+ # symbols as option values.
232
+ #
233
+ # See: https://github.com/puma/puma/issues/1193#issuecomment-305995488
234
+ auth_token = 'none'
235
+ else
236
+ auth_token = opts[:auth_token]
237
+ auth_token ||= Configuration.random_token
238
+ end
239
+
240
+ @options[:control_auth_token] = auth_token
241
+ @options[:control_url_umask] = opts[:umask] if opts[:umask]
242
+ end
243
+
244
+ # Load additional configuration from a file.
245
+ # Files get loaded later via Configuration#load.
246
+ #
247
+ # @example
248
+ # load 'config/puma/production.rb'
249
+ #
250
+ def load(file)
251
+ @options[:config_files] ||= []
252
+ @options[:config_files] << file
253
+ end
254
+
255
+ # Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
256
+ # accepted protocols. Multiple urls can be bound to, calling +bind+ does
257
+ # not overwrite previous bindings.
258
+ #
259
+ # The default is "tcp://0.0.0.0:9292".
260
+ #
261
+ # You can use query parameters within the url to specify options:
262
+ #
263
+ # * Set the socket backlog depth with +backlog+, default is 1024.
264
+ # * Set up an SSL certificate with +key+ & +cert+.
265
+ # * Set up an SSL certificate for mTLS with +key+, +cert+, +ca+ and +verify_mode+.
266
+ # * Set whether to optimize for low latency instead of throughput with
267
+ # +low_latency+, default is to not optimize for low latency. This is done
268
+ # via +Socket::TCP_NODELAY+.
269
+ # * Set socket permissions with +umask+.
270
+ #
271
+ # @example Backlog depth
272
+ # bind 'unix:///var/run/puma.sock?backlog=512'
273
+ # @example SSL cert
274
+ # bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
275
+ # @example SSL cert for mutual TLS (mTLS)
276
+ # bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem&ca=ca.pem&verify_mode=force_peer'
277
+ # @example Disable optimization for low latency
278
+ # bind 'tcp://0.0.0.0:9292?low_latency=false'
279
+ # @example Socket permissions
280
+ # bind 'unix:///var/run/puma.sock?umask=0111'
281
+ #
282
+ # @see Puma::Runner#load_and_bind
283
+ # @see Puma::Cluster#run
284
+ #
285
+ def bind(url)
286
+ @options[:binds] ||= []
287
+ @options[:binds] << url
288
+ end
289
+
290
+ def clear_binds!
291
+ @options[:binds] = []
292
+ end
293
+
294
+ # Bind to (systemd) activated sockets, regardless of configured binds.
295
+ #
296
+ # Systemd can present sockets as file descriptors that are already opened.
297
+ # By default Puma will use these but only if it was explicitly told to bind
298
+ # to the socket. If not, it will close the activated sockets. This means
299
+ # all configuration is duplicated.
300
+ #
301
+ # Binds can contain additional configuration, but only SSL config is really
302
+ # relevant since the unix and TCP socket options are ignored.
303
+ #
304
+ # This means there is a lot of duplicated configuration for no additional
305
+ # value in most setups. This method tells the launcher to bind to all
306
+ # activated sockets, regardless of existing bind.
307
+ #
308
+ # To clear configured binds, the value only can be passed. This will clear
309
+ # out any binds that may have been configured.
310
+ #
311
+ # @example Use any systemd activated sockets as well as configured binds
312
+ # bind_to_activated_sockets
313
+ #
314
+ # @example Only bind to systemd activated sockets, ignoring other binds
315
+ # bind_to_activated_sockets 'only'
316
+ #
317
+ def bind_to_activated_sockets(bind=true)
318
+ @options[:bind_to_activated_sockets] = bind
319
+ end
320
+
321
+ # Define the TCP port to bind to. Use `bind` for more advanced options.
322
+ #
323
+ # The default is +9292+.
324
+ #
325
+ # @example
326
+ # port 3000
327
+ #
328
+ def port(port, host=nil)
329
+ host ||= default_host
330
+ bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
331
+ end
332
+
333
+ # Define how long the tcp socket stays open, if no data has been received.
334
+ #
335
+ # The default is 30 seconds.
336
+ #
337
+ # @example
338
+ # first_data_timeout 40
339
+ #
340
+ # @see Puma::Server.new
341
+ #
342
+ def first_data_timeout(seconds)
343
+ @options[:first_data_timeout] = Integer(seconds)
344
+ end
345
+
346
+ # Define how long persistent connections can be idle before Puma closes them.
347
+ #
348
+ # The default is 20 seconds.
349
+ #
350
+ # @example
351
+ # persistent_timeout 30
352
+ #
353
+ # @see Puma::Server.new
354
+ #
355
+ def persistent_timeout(seconds)
356
+ @options[:persistent_timeout] = Integer(seconds)
357
+ end
358
+
359
+ # If a new request is not received within this number of seconds, begin shutting down.
360
+ #
361
+ # The default is +nil+.
362
+ #
363
+ # @example
364
+ # idle_timeout 60
365
+ #
366
+ # @see Puma::Server.new
367
+ #
368
+ def idle_timeout(seconds)
369
+ @options[:idle_timeout] = Integer(seconds)
370
+ end
371
+
372
+ # Work around leaky apps that leave garbage in Thread locals
373
+ # across requests.
374
+ #
375
+ # The default is +false+.
376
+ #
377
+ # @example
378
+ # clean_thread_locals
379
+ #
380
+ def clean_thread_locals(which=true)
381
+ @options[:clean_thread_locals] = which
382
+ end
383
+
384
+ # When shutting down, drain the accept socket of pending connections and
385
+ # process them. This loops over the accept socket until there are no more
386
+ # read events and then stops looking and waits for the requests to finish.
387
+ #
388
+ # @see Puma::Server#graceful_shutdown
389
+ #
390
+ def drain_on_shutdown(which=true)
391
+ @options[:drain_on_shutdown] = which
392
+ end
393
+
394
+ # Set the environment in which the rack's app will run. The value must be
395
+ # a string.
396
+ #
397
+ # The default is "development".
398
+ #
399
+ # @example
400
+ # environment 'production'
401
+ #
402
+ def environment(environment)
403
+ @options[:environment] = environment
404
+ end
405
+
406
+ # How long to wait for threads to stop when shutting them down.
407
+ # Specifying :immediately will cause Puma to kill the threads immediately.
408
+ # Otherwise the value is the number of seconds to wait.
409
+ #
410
+ # Puma always waits a few seconds after killing a thread for it to try
411
+ # to finish up it's work, even in :immediately mode.
412
+ #
413
+ # The default is +:forever+.
414
+ #
415
+ # @see Puma::Server#graceful_shutdown
416
+ #
417
+ def force_shutdown_after(val=:forever)
418
+ i = case val
419
+ when :forever
420
+ -1
421
+ when :immediately
422
+ 0
423
+ else
424
+ Float(val)
425
+ end
426
+
427
+ @options[:force_shutdown_after] = i
428
+ end
429
+
430
+ # Code to run before doing a restart. This code should
431
+ # close log files, database connections, etc.
432
+ #
433
+ # This can be called multiple times to add code each time.
434
+ #
435
+ # @example
436
+ # on_restart do
437
+ # puts 'On restart...'
438
+ # end
439
+ #
440
+ def on_restart(&block)
441
+ @options[:on_restart] ||= []
442
+ @options[:on_restart] << block
443
+ end
444
+
445
+ # Command to use to restart Puma. This should be just how to
446
+ # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
447
+ # to Puma, as those are the same as the original process.
448
+ #
449
+ # @example
450
+ # restart_command '/u/app/lolcat/bin/restart_puma'
451
+ #
452
+ def restart_command(cmd)
453
+ @options[:restart_cmd] = cmd.to_s
454
+ end
455
+
456
+ # Store the pid of the server in the file at "path".
457
+ #
458
+ # @example
459
+ # pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
460
+ #
461
+ def pidfile(path)
462
+ @options[:pidfile] = path.to_s
463
+ end
464
+
465
+ # Disable request logging, the inverse of `log_requests`.
466
+ #
467
+ # The default is +true+.
468
+ #
469
+ # @example
470
+ # quiet
471
+ #
472
+ def quiet(which=true)
473
+ @options[:log_requests] = !which
474
+ end
475
+
476
+ # Enable request logging, the inverse of `quiet`.
477
+ #
478
+ # The default is +false+.
479
+ #
480
+ # @example
481
+ # log_requests
482
+ #
483
+ def log_requests(which=true)
484
+ @options[:log_requests] = which
485
+ end
486
+
487
+ # Pass in a custom logging class instance
488
+ #
489
+ # @example
490
+ # custom_logger Logger.new('t.log')
491
+ #
492
+ def custom_logger(custom_logger)
493
+ @options[:custom_logger] = custom_logger
494
+ end
495
+
496
+ # Show debugging info
497
+ #
498
+ # The default is +false+.
499
+ #
500
+ # @example
501
+ # debug
502
+ #
503
+ def debug
504
+ @options[:debug] = true
505
+ end
506
+
507
+ # Load +path+ as a rackup file.
508
+ #
509
+ # The default is "config.ru".
510
+ #
511
+ # @example
512
+ # rackup '/u/apps/lolcat/config.ru'
513
+ #
514
+ def rackup(path)
515
+ @options[:rackup] ||= path.to_s
516
+ end
517
+
518
+ # Allows setting `env['rack.url_scheme']`.
519
+ # Only necessary if X-Forwarded-Proto is not being set by your proxy
520
+ # Normal values are 'http' or 'https'.
521
+ #
522
+ def rack_url_scheme(scheme=nil)
523
+ @options[:rack_url_scheme] = scheme
524
+ end
525
+
526
+ # Enable HTTP 103 Early Hints responses.
527
+ #
528
+ # The default is +nil+.
529
+ #
530
+ # @example
531
+ # early_hints
532
+ #
533
+ def early_hints(answer=true)
534
+ @options[:early_hints] = answer
535
+ end
536
+
537
+ # Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
538
+ # specifies whether the output is appended.
539
+ #
540
+ # The default is +false+.
541
+ #
542
+ # @example
543
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
544
+ # @example
545
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
546
+ #
547
+ def stdout_redirect(stdout=nil, stderr=nil, append=false)
548
+ @options[:redirect_stdout] = stdout
549
+ @options[:redirect_stderr] = stderr
550
+ @options[:redirect_append] = append
551
+ end
552
+
553
+ def log_formatter(&block)
554
+ @options[:log_formatter] = block
555
+ end
556
+
557
+ # Configure the number of threads to use to answer requests.
558
+ #
559
+ # It can be a single fixed number, or a +min+ and a +max+.
560
+ #
561
+ # The default is the environment variables +PUMA_MIN_THREADS+ / +PUMA_MAX_THREADS+
562
+ # (or +MIN_THREADS+ / +MAX_THREADS+ if the +PUMA_+ variables aren't set).
563
+ #
564
+ # If these environment variables aren't set, the default is "0, 5" in MRI or "0, 16" for other interpreters.
565
+ #
566
+ # @example
567
+ # threads 5
568
+ # @example
569
+ # threads 0, 16
570
+ # @example
571
+ # threads 5, 5
572
+ #
573
+ def threads(min, max = min)
574
+ min = Integer(min)
575
+ max = Integer(max)
576
+ if min > max
577
+ raise "The minimum (#{min}) number of threads must be less than or equal to the max (#{max})"
578
+ end
579
+
580
+ if max < 1
581
+ raise "The maximum number of threads (#{max}) must be greater than 0"
582
+ end
583
+
584
+ @options[:min_threads] = min
585
+ @options[:max_threads] = max
586
+ end
587
+
588
+ # Instead of using +bind+ and manually constructing a URI like:
589
+ #
590
+ # bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
591
+ #
592
+ # you can use the this method.
593
+ #
594
+ # When binding on localhost you don't need to specify +cert+ and +key+,
595
+ # Puma will assume you are using the +localhost+ gem and try to load the
596
+ # appropriate files.
597
+ #
598
+ # When using the options hash parameter, the `reuse:` value is either
599
+ # `true`, which sets reuse 'on' with default values, or a hash, with `:size`
600
+ # and/or `:timeout` keys, each with integer values.
601
+ #
602
+ # The `cert:` options hash parameter can be the path to a certificate
603
+ # file including all intermediate certificates in PEM format.
604
+ #
605
+ # The `cert_pem:` options hash parameter can be String containing the
606
+ # cerificate and all intermediate certificates in PEM format.
607
+ #
608
+ # @example
609
+ # ssl_bind '127.0.0.1', '9292', {
610
+ # cert: path_to_cert,
611
+ # key: path_to_key,
612
+ # ssl_cipher_filter: cipher_filter, # optional
613
+ # ssl_ciphersuites: ciphersuites, # optional
614
+ # verify_mode: verify_mode, # default 'none'
615
+ # verification_flags: flags, # optional, not supported by JRuby
616
+ # reuse: true # optional
617
+ # }
618
+ #
619
+ # @example Using self-signed certificate with the +localhost+ gem:
620
+ # ssl_bind '127.0.0.1', '9292'
621
+ #
622
+ # @example Alternatively, you can provide +cert_pem+ and +key_pem+:
623
+ # ssl_bind '127.0.0.1', '9292', {
624
+ # cert_pem: File.read(path_to_cert),
625
+ # key_pem: File.read(path_to_key),
626
+ # reuse: {size: 2_000, timeout: 20} # optional
627
+ # }
628
+ #
629
+ # @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
630
+ # ssl_bind '127.0.0.1', '9292', {
631
+ # keystore: path_to_keystore,
632
+ # keystore_pass: password,
633
+ # ssl_cipher_list: cipher_list, # optional
634
+ # verify_mode: verify_mode # default 'none'
635
+ # }
636
+ #
637
+ def ssl_bind(host, port, opts = {})
638
+ add_pem_values_to_options_store(opts)
639
+ bind self.class.ssl_bind_str(host, port, opts)
640
+ end
641
+
642
+ # Use +path+ as the file to store the server info state. This is
643
+ # used by +pumactl+ to query and control the server.
644
+ #
645
+ # @example
646
+ # state_path '/u/apps/lolcat/tmp/pids/puma.state'
647
+ #
648
+ def state_path(path)
649
+ @options[:state] = path.to_s
650
+ end
651
+
652
+ # Use +permission+ to restrict permissions for the state file.
653
+ #
654
+ # @example
655
+ # state_permission 0600
656
+ #
657
+ # @version 5.0.0
658
+ #
659
+ def state_permission(permission)
660
+ @options[:state_permission] = permission
661
+ end
662
+
663
+ # How many worker processes to run. Typically this is set to
664
+ # the number of available cores.
665
+ #
666
+ # The default is the value of the environment variable +WEB_CONCURRENCY+ if
667
+ # set, otherwise 0.
668
+ #
669
+ # @note Cluster mode only.
670
+ #
671
+ # @example
672
+ # workers 2
673
+ #
674
+ # @see Puma::Cluster
675
+ #
676
+ def workers(count)
677
+ @options[:workers] = count.to_i
678
+ end
679
+
680
+ # Disable warning message when running in cluster mode with a single worker.
681
+ #
682
+ # Cluster mode has some overhead of running an additional 'control' process
683
+ # in order to manage the cluster. If only running a single worker it is
684
+ # likely not worth paying that overhead vs running in single mode with
685
+ # additional threads instead.
686
+ #
687
+ # There are some scenarios where running cluster mode with a single worker
688
+ # may still be warranted and valid under certain deployment scenarios, see
689
+ # https://github.com/puma/puma/issues/2534
690
+ #
691
+ # Moving from workers = 1 to workers = 0 will save 10-30% of memory use.
692
+ #
693
+ # The default is +false+.
694
+ #
695
+ # @note Cluster mode only.
696
+ #
697
+ # @example
698
+ # silence_single_worker_warning
699
+ #
700
+ def silence_single_worker_warning
701
+ @options[:silence_single_worker_warning] = true
702
+ end
703
+
704
+ # Disable warning message when running single mode with callback hook defined.
705
+ #
706
+ # The default is +false+.
707
+ #
708
+ # @example
709
+ # silence_fork_callback_warning
710
+ #
711
+ def silence_fork_callback_warning
712
+ @options[:silence_fork_callback_warning] = true
713
+ end
714
+
715
+ # Code to run immediately before master process
716
+ # forks workers (once on boot). These hooks can block if necessary
717
+ # to wait for background operations unknown to Puma to finish before
718
+ # the process terminates.
719
+ # This can be used to close any connections to remote servers (database,
720
+ # Redis, ...) that were opened when preloading the code.
721
+ #
722
+ # This can be called multiple times to add several hooks.
723
+ #
724
+ # @note Cluster mode only.
725
+ #
726
+ # @example
727
+ # before_fork do
728
+ # puts "Starting workers..."
729
+ # end
730
+ #
731
+ def before_fork(&block)
732
+ warn_if_in_single_mode('before_fork')
733
+
734
+ @options[:before_fork] ||= []
735
+ @options[:before_fork] << block
736
+ end
737
+
738
+ # Code to run in a worker when it boots to setup
739
+ # the process before booting the app.
740
+ #
741
+ # This can be called multiple times to add several hooks.
742
+ #
743
+ # @note Cluster mode only.
744
+ #
745
+ # @example
746
+ # on_worker_boot do
747
+ # puts 'Before worker boot...'
748
+ # end
749
+ #
750
+ def on_worker_boot(key = nil, &block)
751
+ warn_if_in_single_mode('on_worker_boot')
752
+
753
+ process_hook :before_worker_boot, key, block, 'on_worker_boot'
754
+ end
755
+
756
+ # Code to run immediately before a worker shuts
757
+ # down (after it has finished processing HTTP requests). The worker's
758
+ # index is passed as an argument. These hooks
759
+ # can block if necessary to wait for background operations unknown
760
+ # to Puma to finish before the process terminates.
761
+ #
762
+ # This can be called multiple times to add several hooks.
763
+ #
764
+ # @note Cluster mode only.
765
+ #
766
+ # @example
767
+ # on_worker_shutdown do
768
+ # puts 'On worker shutdown...'
769
+ # end
770
+ #
771
+ def on_worker_shutdown(key = nil, &block)
772
+ warn_if_in_single_mode('on_worker_shutdown')
773
+
774
+ process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
775
+ end
776
+
777
+ # Code to run in the master right before a worker is started. The worker's
778
+ # index is passed as an argument.
779
+ #
780
+ # This can be called multiple times to add several hooks.
781
+ #
782
+ # @note Cluster mode only.
783
+ #
784
+ # @example
785
+ # on_worker_fork do
786
+ # puts 'Before worker fork...'
787
+ # end
788
+ #
789
+ def on_worker_fork(&block)
790
+ warn_if_in_single_mode('on_worker_fork')
791
+
792
+ process_hook :before_worker_fork, nil, block, 'on_worker_fork'
793
+ end
794
+
795
+ # Code to run in the master after a worker has been started. The worker's
796
+ # index is passed as an argument.
797
+ #
798
+ # This is called everytime a worker is to be started.
799
+ #
800
+ # @note Cluster mode only.
801
+ #
802
+ # @example
803
+ # after_worker_fork do
804
+ # puts 'After worker fork...'
805
+ # end
806
+ #
807
+ def after_worker_fork(&block)
808
+ warn_if_in_single_mode('after_worker_fork')
809
+
810
+ process_hook :after_worker_fork, nil, block, 'after_worker_fork'
811
+ end
812
+
813
+ alias_method :after_worker_boot, :after_worker_fork
814
+
815
+ # Code to run after puma is booted (works for both: single and clustered)
816
+ #
817
+ # @example
818
+ # on_booted do
819
+ # puts 'After booting...'
820
+ # end
821
+ #
822
+ def on_booted(&block)
823
+ @config.options[:events].on_booted(&block)
824
+ end
825
+
826
+ # Code to run after puma is stopped (works for both: single and clustered)
827
+ #
828
+ # @example
829
+ # on_stopped do
830
+ # puts 'After stopping...'
831
+ # end
832
+ #
833
+ def on_stopped(&block)
834
+ @config.options[:events].on_stopped(&block)
835
+ end
836
+
837
+ # When `fork_worker` is enabled, code to run in Worker 0
838
+ # before all other workers are re-forked from this process,
839
+ # after the server has temporarily stopped serving requests
840
+ # (once per complete refork cycle).
841
+ #
842
+ # This can be used to trigger extra garbage-collection to maximize
843
+ # copy-on-write efficiency, or close any connections to remote servers
844
+ # (database, Redis, ...) that were opened while the server was running.
845
+ #
846
+ # This can be called multiple times to add several hooks.
847
+ #
848
+ # @note Cluster mode with `fork_worker` enabled only.
849
+ #
850
+ # @example
851
+ # on_refork do
852
+ # 3.times {GC.start}
853
+ # end
854
+ #
855
+ # @version 5.0.0
856
+ #
857
+ def on_refork(key = nil, &block)
858
+ process_hook :before_refork, key, block, 'on_refork'
859
+ end
860
+
861
+ # Provide a block to be executed just before a thread is added to the thread
862
+ # pool. Be careful: while the block executes, thread creation is delayed, and
863
+ # probably a request will have to wait too! The new thread will not be added to
864
+ # the threadpool until the provided block returns.
865
+ #
866
+ # Return values are ignored.
867
+ # Raising an exception will log a warning.
868
+ #
869
+ # This hook is useful for doing something when the thread pool grows.
870
+ #
871
+ # This can be called multiple times to add several hooks.
872
+ #
873
+ # @example
874
+ # on_thread_start do
875
+ # puts 'On thread start...'
876
+ # end
877
+ #
878
+ def on_thread_start(&block)
879
+ @options[:before_thread_start] ||= []
880
+ @options[:before_thread_start] << block
881
+ end
882
+
883
+ # Provide a block to be executed after a thread is trimmed from the thread
884
+ # pool. Be careful: while this block executes, Puma's main loop is
885
+ # blocked, so no new requests will be picked up.
886
+ #
887
+ # This hook only runs when a thread in the threadpool is trimmed by Puma.
888
+ # It does not run when a thread dies due to exceptions or any other cause.
889
+ #
890
+ # Return values are ignored.
891
+ # Raising an exception will log a warning.
892
+ #
893
+ # This hook is useful for cleaning up thread local resources when a thread
894
+ # is trimmed.
895
+ #
896
+ # This can be called multiple times to add several hooks.
897
+ #
898
+ # @example
899
+ # on_thread_exit do
900
+ # puts 'On thread exit...'
901
+ # end
902
+ #
903
+ def on_thread_exit(&block)
904
+ @options[:before_thread_exit] ||= []
905
+ @options[:before_thread_exit] << block
906
+ end
907
+
908
+ # Code to run out-of-band when the worker is idle.
909
+ # These hooks run immediately after a request has finished
910
+ # processing and there are no busy threads on the worker.
911
+ # The worker doesn't accept new requests until this code finishes.
912
+ #
913
+ # This hook is useful for running out-of-band garbage collection
914
+ # or scheduling asynchronous tasks to execute after a response.
915
+ #
916
+ # This can be called multiple times to add several hooks.
917
+ #
918
+ def out_of_band(&block)
919
+ process_hook :out_of_band, nil, block, 'out_of_band'
920
+ end
921
+
922
+ # The directory to operate out of.
923
+ #
924
+ # The default is the current directory.
925
+ #
926
+ # @example
927
+ # directory '/u/apps/lolcat'
928
+ #
929
+ def directory(dir)
930
+ @options[:directory] = dir.to_s
931
+ end
932
+
933
+ # Preload the application before starting the workers; this conflicts with
934
+ # phased restart feature.
935
+ #
936
+ # The default is +true+ if your app uses more than 1 worker.
937
+ #
938
+ # @note Cluster mode only.
939
+ #
940
+ # @example
941
+ # preload_app!
942
+ #
943
+ def preload_app!(answer=true)
944
+ @options[:preload_app] = answer
945
+ end
946
+
947
+ # Use +obj+ or +block+ as the low level error handler. This allows the
948
+ # configuration file to change the default error on the server.
949
+ #
950
+ # @example
951
+ # lowlevel_error_handler do |err|
952
+ # [200, {}, ["error page"]]
953
+ # end
954
+ #
955
+ def lowlevel_error_handler(obj=nil, &block)
956
+ obj ||= block
957
+ raise "Provide either a #call'able or a block" unless obj
958
+ @options[:lowlevel_error_handler] = obj
959
+ end
960
+
961
+ # This option is used to allow your app and its gems to be
962
+ # properly reloaded when not using preload.
963
+ #
964
+ # When set, if Puma detects that it's been invoked in the
965
+ # context of Bundler, it will cleanup the environment and
966
+ # re-run itself outside the Bundler environment, but directly
967
+ # using the files that Bundler has setup.
968
+ #
969
+ # This means that Puma is now decoupled from your Bundler
970
+ # context and when each worker loads, it will be loading a
971
+ # new Bundler context and thus can float around as the release
972
+ # dictates.
973
+ #
974
+ # @note This is incompatible with +preload_app!+.
975
+ # @note This is only supported for RubyGems 2.2+
976
+ #
977
+ # @see extra_runtime_dependencies
978
+ #
979
+ def prune_bundler(answer=true)
980
+ @options[:prune_bundler] = answer
981
+ end
982
+
983
+ # Raises a SignalException when SIGTERM is received. In environments where
984
+ # SIGTERM is something expected, you can suppress these with this option.
985
+ #
986
+ # This can be useful for example in Kubernetes, where rolling restart is
987
+ # guaranteed usually on the infrastructure level.
988
+ #
989
+ # The default is +true+.
990
+ #
991
+ # @example
992
+ # raise_exception_on_sigterm false
993
+ #
994
+ # @see Puma::Launcher#setup_signals
995
+ # @see Puma::Cluster#setup_signals
996
+ #
997
+ def raise_exception_on_sigterm(answer=true)
998
+ @options[:raise_exception_on_sigterm] = answer
999
+ end
1000
+
1001
+ # When using prune_bundler, if extra runtime dependencies need to be loaded to
1002
+ # initialize your app, then this setting can be used. This includes any Puma plugins.
1003
+ #
1004
+ # Before bundler is pruned, the gem names supplied will be looked up in the bundler
1005
+ # context and then loaded again after bundler is pruned.
1006
+ # Only applies if prune_bundler is used.
1007
+ #
1008
+ # @example
1009
+ # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
1010
+ # @example
1011
+ # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
1012
+ #
1013
+ # @see Puma::Launcher#extra_runtime_deps_directories
1014
+ #
1015
+ def extra_runtime_dependencies(answer = [])
1016
+ @options[:extra_runtime_dependencies] = Array(answer)
1017
+ end
1018
+
1019
+ # Additional text to display in process listing.
1020
+ #
1021
+ # If you do not specify a tag, Puma will infer it. If you do not want Puma
1022
+ # to add a tag, use an empty string.
1023
+ #
1024
+ # The default is the current file or directory base name.
1025
+ #
1026
+ # @example
1027
+ # tag 'app name'
1028
+ # @example
1029
+ # tag ''
1030
+ #
1031
+ def tag(string)
1032
+ @options[:tag] = string.to_s
1033
+ end
1034
+
1035
+ # Change the default interval for checking workers.
1036
+ #
1037
+ # The default is 5 seconds.
1038
+ #
1039
+ # @note Cluster mode only.
1040
+ #
1041
+ # @example
1042
+ # worker_check_interval 10
1043
+ #
1044
+ # @see Puma::Cluster#check_workers
1045
+ #
1046
+ def worker_check_interval(interval)
1047
+ @options[:worker_check_interval] = Integer(interval)
1048
+ end
1049
+
1050
+ # Verifies that all workers have checked in to the master process within
1051
+ # the given timeout. If not the worker process will be restarted. This is
1052
+ # not a request timeout, it is to protect against a hung or dead process.
1053
+ # Setting this value will not protect against slow requests.
1054
+ #
1055
+ # This value must be greater than worker_check_interval.
1056
+ #
1057
+ # The default is 60 seconds.
1058
+ #
1059
+ # @note Cluster mode only.
1060
+ #
1061
+ # @example
1062
+ # worker_timeout 60
1063
+ #
1064
+ # @see Puma::Cluster::Worker#ping_timeout
1065
+ #
1066
+ def worker_timeout(timeout)
1067
+ timeout = Integer(timeout)
1068
+ min = @options.fetch(:worker_check_interval, Configuration::DEFAULTS[:worker_check_interval])
1069
+
1070
+ if timeout <= min
1071
+ raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
1072
+ end
1073
+
1074
+ @options[:worker_timeout] = timeout
1075
+ end
1076
+
1077
+ # Change the default worker timeout for booting.
1078
+ #
1079
+ # The default is the value of `worker_timeout`.
1080
+ #
1081
+ # @note Cluster mode only.
1082
+ #
1083
+ # @example
1084
+ # worker_boot_timeout 60
1085
+ #
1086
+ # @see Puma::Cluster::Worker#ping_timeout
1087
+ #
1088
+ def worker_boot_timeout(timeout)
1089
+ @options[:worker_boot_timeout] = Integer(timeout)
1090
+ end
1091
+
1092
+ # Set the timeout for worker shutdown.
1093
+ #
1094
+ # The default is 60 seconds.
1095
+ #
1096
+ # @note Cluster mode only.
1097
+ #
1098
+ # @example
1099
+ # worker_shutdown_timeout 90
1100
+ #
1101
+ # @see Puma::Cluster::Worker#term
1102
+ #
1103
+ def worker_shutdown_timeout(timeout)
1104
+ @options[:worker_shutdown_timeout] = Integer(timeout)
1105
+ end
1106
+
1107
+ # Set the strategy for worker culling.
1108
+ #
1109
+ # There are two possible values:
1110
+ #
1111
+ # 1. **:youngest** - the youngest workers (i.e. the workers that were
1112
+ # the most recently started) will be culled.
1113
+ # 2. **:oldest** - the oldest workers (i.e. the workers that were started
1114
+ # the longest time ago) will be culled.
1115
+ #
1116
+ # The default is +:youngest+.
1117
+ #
1118
+ # @note Cluster mode only.
1119
+ #
1120
+ # @example
1121
+ # worker_culling_strategy :oldest
1122
+ #
1123
+ # @see Puma::Cluster#cull_workers
1124
+ #
1125
+ def worker_culling_strategy(strategy)
1126
+ stategy = strategy.to_sym
1127
+
1128
+ if ![:youngest, :oldest].include?(strategy)
1129
+ raise "Invalid value for worker_culling_strategy - #{stategy}"
1130
+ end
1131
+
1132
+ @options[:worker_culling_strategy] = strategy
1133
+ end
1134
+
1135
+ # When set to true, workers accept all requests
1136
+ # and queue them before passing them to the handlers.
1137
+ # When set to false, each worker process accepts exactly as
1138
+ # many requests as it is configured to simultaneously handle.
1139
+ #
1140
+ # Queueing requests generally improves performance. In some
1141
+ # cases, such as a single threaded application, it may be
1142
+ # better to ensure requests get balanced across workers.
1143
+ #
1144
+ # Note that setting this to false disables HTTP keepalive and
1145
+ # slow clients will occupy a handler thread while the request
1146
+ # is being sent. A reverse proxy, such as nginx, can handle
1147
+ # slow clients and queue requests before they reach Puma.
1148
+ #
1149
+ # The default is +true+.
1150
+ #
1151
+ # @see Puma::Server
1152
+ #
1153
+ def queue_requests(answer=true)
1154
+ @options[:queue_requests] = answer
1155
+ end
1156
+
1157
+ # When a shutdown is requested, the backtraces of all the
1158
+ # threads will be written to $stdout. This can help figure
1159
+ # out why shutdown is hanging.
1160
+ #
1161
+ def shutdown_debug(val=true)
1162
+ @options[:shutdown_debug] = val
1163
+ end
1164
+
1165
+
1166
+ # Attempts to route traffic to less-busy workers by causing them to delay
1167
+ # listening on the socket, allowing workers which are not processing any
1168
+ # requests to pick up new requests first.
1169
+ #
1170
+ # The default is 0.005 seconds.
1171
+ #
1172
+ # Only works on MRI. For all other interpreters, this setting does nothing.
1173
+ #
1174
+ # @see Puma::Server#handle_servers
1175
+ # @see Puma::ThreadPool#wait_for_less_busy_worker
1176
+ #
1177
+ # @version 5.0.0
1178
+ #
1179
+ def wait_for_less_busy_worker(val=0.005)
1180
+ @options[:wait_for_less_busy_worker] = val.to_f
1181
+ end
1182
+
1183
+ # Control how the remote address of the connection is set. This
1184
+ # is configurable because to calculate the true socket peer address
1185
+ # a kernel syscall is required which for very fast rack handlers
1186
+ # slows down the handling significantly.
1187
+ #
1188
+ # There are 5 possible values:
1189
+ #
1190
+ # 1. **:socket** - read the peername from the socket using the
1191
+ # syscall. This is the normal behavior. If this fails for any reason (e.g.,
1192
+ # if the peer disconnects between the connection being accepted and the getpeername
1193
+ # system call), Puma will return "0.0.0.0"
1194
+ # 2. **:localhost** - set the remote address to "127.0.0.1"
1195
+ # 3. **header: <http_header>**- set the remote address to the value of the
1196
+ # provided http header. For instance:
1197
+ # `set_remote_address header: "X-Real-IP"`.
1198
+ # Only the first word (as separated by spaces or comma) is used, allowing
1199
+ # headers such as X-Forwarded-For to be used as well. If this header is absent,
1200
+ # Puma will fall back to the behavior of :socket
1201
+ # 4. **proxy_protocol: :v1**- set the remote address to the value read from the
1202
+ # HAproxy PROXY protocol, version 1. If the request does not have the PROXY
1203
+ # protocol attached to it, will fall back to :socket
1204
+ # 5. **\<Any string\>** - this allows you to hardcode remote address to any value
1205
+ # you wish. Because Puma never uses this field anyway, it's format is
1206
+ # entirely in your hands.
1207
+ #
1208
+ # The default is +:socket+.
1209
+ #
1210
+ # @example
1211
+ # set_remote_address :localhost
1212
+ #
1213
+ def set_remote_address(val=:socket)
1214
+ case val
1215
+ when :socket
1216
+ @options[:remote_address] = val
1217
+ when :localhost
1218
+ @options[:remote_address] = :value
1219
+ @options[:remote_address_value] = "127.0.0.1".freeze
1220
+ when String
1221
+ @options[:remote_address] = :value
1222
+ @options[:remote_address_value] = val
1223
+ when Hash
1224
+ if hdr = val[:header]
1225
+ @options[:remote_address] = :header
1226
+ @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
1227
+ elsif protocol_version = val[:proxy_protocol]
1228
+ @options[:remote_address] = :proxy_protocol
1229
+ protocol_version = protocol_version.downcase.to_sym
1230
+ unless [:v1].include?(protocol_version)
1231
+ raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
1232
+ end
1233
+ @options[:remote_address_proxy_protocol] = protocol_version
1234
+ else
1235
+ raise "Invalid value for set_remote_address - #{val.inspect}"
1236
+ end
1237
+ else
1238
+ raise "Invalid value for set_remote_address - #{val}"
1239
+ end
1240
+ end
1241
+
1242
+ # When enabled, workers will be forked from worker 0 instead of from the master process.
1243
+ # This option is similar to `preload_app` because the app is preloaded before forking,
1244
+ # but it is compatible with phased restart.
1245
+ #
1246
+ # This option also enables the `refork` command (SIGURG), which optimizes copy-on-write performance
1247
+ # in a running app.
1248
+ #
1249
+ # A refork will automatically trigger once after the specified number of requests
1250
+ # (default 1000), or pass 0 to disable auto refork.
1251
+ #
1252
+ # @note Cluster mode only.
1253
+ #
1254
+ # @version 5.0.0
1255
+ #
1256
+ def fork_worker(after_requests=1000)
1257
+ @options[:fork_worker] = Integer(after_requests)
1258
+ end
1259
+
1260
+ # The number of requests to attempt inline before sending a client back to
1261
+ # the reactor to be subject to normal ordering.
1262
+ #
1263
+ # The default is 10.
1264
+ #
1265
+ # @example
1266
+ # max_fast_inline 20
1267
+ #
1268
+ def max_fast_inline(num_of_requests)
1269
+ @options[:max_fast_inline] = Float(num_of_requests)
1270
+ end
1271
+
1272
+ # When `true`, keep-alive connections are maintained on inbound requests.
1273
+ # Enabling this setting reduces the number of TCP operations, reducing response
1274
+ # times for connections that can send multiple requests in a single connection.
1275
+ #
1276
+ # When Puma receives more incoming connections than available Puma threads,
1277
+ # enabling the keep-alive behavior may result in processing requests out-of-order,
1278
+ # increasing overall response time variance. Increased response time variance
1279
+ # means that the overall average of response times might not change, but more
1280
+ # outliers will exist. Those long-tail outliers may significantly affect response
1281
+ # times for some processed requests.
1282
+ #
1283
+ # When `false`, Puma closes the connection after each request, requiring the
1284
+ # client to open a new request. Disabling this setting guarantees that requests
1285
+ # will be processed in the order they are fully received, decreasing response
1286
+ # variance and eliminating long-tail outliers caused by keep-alive behavior.
1287
+ # The trade-off is that the number of TCP operations required will increase.
1288
+ #
1289
+ # The default is +true+.
1290
+ #
1291
+ # @example
1292
+ # enable_keep_alives false
1293
+ #
1294
+ def enable_keep_alives(enabled=true)
1295
+ @options[:enable_keep_alives] = enabled
1296
+ end
1297
+
1298
+ # Specify the backend for the IO selector.
1299
+ #
1300
+ # Provided values will be passed directly to +NIO::Selector.new+, with the
1301
+ # exception of +:auto+ which will let nio4r choose the backend.
1302
+ #
1303
+ # Check the documentation of +NIO::Selector.backends+ for the list of valid
1304
+ # options. Note that the available options on your system will depend on the
1305
+ # operating system. If you want to use the pure Ruby backend (not
1306
+ # recommended due to its comparatively low performance), set environment
1307
+ # variable +NIO4R_PURE+ to +true+.
1308
+ #
1309
+ # The default is +:auto+.
1310
+ #
1311
+ # @see https://github.com/socketry/nio4r/blob/master/lib/nio/selector.rb
1312
+ #
1313
+ def io_selector_backend(backend)
1314
+ @options[:io_selector_backend] = backend.to_sym
1315
+ end
1316
+
1317
+ # Ensures +STDOUT+ and +STDERR+ is immediately flushed to the underlying
1318
+ # operating system and is not buffered internally
1319
+ #
1320
+ # The default is +true+.
1321
+ #
1322
+ # @example
1323
+ # mutate_stdout_and_stderr_to_sync_on_write false
1324
+ #
1325
+ def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
1326
+ @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
1327
+ end
1328
+
1329
+ # Specify how big the request payload should be, in bytes.
1330
+ # This limit is compared against Content-Length HTTP header.
1331
+ # If the payload size (CONTENT_LENGTH) is larger than http_content_length_limit,
1332
+ # HTTP 413 status code is returned.
1333
+ #
1334
+ # When no Content-Length http header is present, it is compared against the
1335
+ # size of the body of the request.
1336
+ #
1337
+ # The default is +nil+.
1338
+ #
1339
+ # @example
1340
+ # http_content_length_limit 2_000_000_000
1341
+ #
1342
+ def http_content_length_limit(limit)
1343
+ @options[:http_content_length_limit] = limit
1344
+ end
1345
+
1346
+ # Supported http methods, which will replace `Puma::Const::SUPPORTED_HTTP_METHODS`.
1347
+ # The value of `:any` will allows all methods, otherwise, the value must be
1348
+ # an array of strings. Note that methods are all uppercase.
1349
+ #
1350
+ # `Puma::Const::SUPPORTED_HTTP_METHODS` is conservative, if you want a
1351
+ # complete set of methods, the methods defined by the
1352
+ # [IANA Method Registry](https://www.iana.org/assignments/http-methods/http-methods.xhtml)
1353
+ # are pre-defined as the constant `Puma::Const::IANA_HTTP_METHODS`.
1354
+ #
1355
+ # @note If the `methods` value is `:any`, no method check with be performed,
1356
+ # similar to Puma v5 and earlier.
1357
+ #
1358
+ # @example Adds 'PROPFIND' to existing supported methods
1359
+ # supported_http_methods(Puma::Const::SUPPORTED_HTTP_METHODS + ['PROPFIND'])
1360
+ # @example Restricts methods to the array elements
1361
+ # supported_http_methods %w[HEAD GET POST PUT DELETE OPTIONS PROPFIND]
1362
+ # @example Restricts methods to the methods in the IANA Registry
1363
+ # supported_http_methods Puma::Const::IANA_HTTP_METHODS
1364
+ # @example Allows any method
1365
+ # supported_http_methods :any
1366
+ #
1367
+ def supported_http_methods(methods)
1368
+ if methods == :any
1369
+ @options[:supported_http_methods] = :any
1370
+ elsif Array === methods && methods == (ary = methods.grep(String).uniq) &&
1371
+ !ary.empty?
1372
+ @options[:supported_http_methods] = ary
1373
+ else
1374
+ raise "supported_http_methods must be ':any' or a unique array of strings"
1375
+ end
1376
+ end
1377
+
1378
+ private
1379
+
1380
+ # To avoid adding cert_pem and key_pem as URI params, we store them on the
1381
+ # options[:store] from where Puma binder knows how to find and extract them.
1382
+ #
1383
+ def add_pem_values_to_options_store(opts)
1384
+ return if defined?(JRUBY_VERSION)
1385
+
1386
+ @options[:store] ||= []
1387
+
1388
+ # Store cert_pem and key_pem to options[:store] if present
1389
+ [:cert, :key].each do |v|
1390
+ opt_key = :"#{v}_pem"
1391
+ if opts[opt_key]
1392
+ index = @options[:store].length
1393
+ @options[:store] << opts[opt_key]
1394
+ opts[v] = "store:#{index}"
1395
+ end
1396
+ end
1397
+ end
1398
+
1399
+ def process_hook(options_key, key, block, meth)
1400
+ @options[options_key] ||= []
1401
+ if ON_WORKER_KEY.include? key.class
1402
+ @options[options_key] << [block, key.to_sym]
1403
+ elsif key.nil?
1404
+ @options[options_key] << block
1405
+ else
1406
+ raise "'#{meth}' key must be String or Symbol"
1407
+ end
1408
+ end
1409
+
1410
+ def warn_if_in_single_mode(hook_name)
1411
+ return if @options[:silence_fork_callback_warning]
1412
+ # user_options (CLI) have precedence over config file
1413
+ workers_val = @config.options.user_options[:workers] || @options[:workers] ||
1414
+ @config.puma_default_options[:workers] || 0
1415
+ if workers_val == 0
1416
+ log_string =
1417
+ "Warning: You specified code to run in a `#{hook_name}` block, " \
1418
+ "but Puma is not configured to run in cluster mode (worker count > 0 ), " \
1419
+ "so your `#{hook_name}` block did not run"
1420
+
1421
+ LogWriter.stdio.log(log_string)
1422
+ end
1423
+ end
1424
+ end
1425
+ end