puma 3.12.1 → 5.6.7

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1608 -447
  3. data/LICENSE +23 -20
  4. data/README.md +175 -63
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +59 -21
  7. data/docs/compile_options.md +21 -0
  8. data/docs/deployment.md +69 -58
  9. data/docs/fork_worker.md +33 -0
  10. data/docs/jungle/README.md +9 -0
  11. data/{tools → docs}/jungle/rc.d/README.md +1 -1
  12. data/{tools → docs}/jungle/rc.d/puma +2 -2
  13. data/docs/kubernetes.md +66 -0
  14. data/docs/nginx.md +1 -1
  15. data/docs/plugins.md +22 -12
  16. data/docs/rails_dev_mode.md +28 -0
  17. data/docs/restart.md +47 -22
  18. data/docs/signals.md +13 -11
  19. data/docs/stats.md +142 -0
  20. data/docs/systemd.md +95 -120
  21. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  22. data/ext/puma_http11/ext_help.h +1 -1
  23. data/ext/puma_http11/extconf.rb +57 -2
  24. data/ext/puma_http11/http11_parser.c +105 -117
  25. data/ext/puma_http11/http11_parser.h +1 -1
  26. data/ext/puma_http11/http11_parser.java.rl +22 -38
  27. data/ext/puma_http11/http11_parser.rl +4 -2
  28. data/ext/puma_http11/http11_parser_common.rl +4 -4
  29. data/ext/puma_http11/mini_ssl.c +339 -98
  30. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  31. data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
  32. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
  33. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +124 -71
  34. data/ext/puma_http11/puma_http11.c +35 -51
  35. data/lib/puma/app/status.rb +71 -49
  36. data/lib/puma/binder.rb +234 -137
  37. data/lib/puma/cli.rb +28 -18
  38. data/lib/puma/client.rb +350 -230
  39. data/lib/puma/cluster/worker.rb +173 -0
  40. data/lib/puma/cluster/worker_handle.rb +94 -0
  41. data/lib/puma/cluster.rb +247 -232
  42. data/lib/puma/commonlogger.rb +2 -2
  43. data/lib/puma/configuration.rb +61 -51
  44. data/lib/puma/const.rb +42 -21
  45. data/lib/puma/control_cli.rb +115 -67
  46. data/lib/puma/detect.rb +29 -2
  47. data/lib/puma/dsl.rb +619 -123
  48. data/lib/puma/error_logger.rb +104 -0
  49. data/lib/puma/events.rb +55 -31
  50. data/lib/puma/io_buffer.rb +7 -5
  51. data/lib/puma/jruby_restart.rb +0 -58
  52. data/lib/puma/json_serialization.rb +96 -0
  53. data/lib/puma/launcher.rb +193 -69
  54. data/lib/puma/minissl/context_builder.rb +81 -0
  55. data/lib/puma/minissl.rb +170 -65
  56. data/lib/puma/null_io.rb +18 -1
  57. data/lib/puma/plugin/tmp_restart.rb +2 -0
  58. data/lib/puma/plugin.rb +7 -13
  59. data/lib/puma/queue_close.rb +26 -0
  60. data/lib/puma/rack/builder.rb +3 -5
  61. data/lib/puma/rack/urlmap.rb +2 -0
  62. data/lib/puma/rack_default.rb +2 -0
  63. data/lib/puma/reactor.rb +85 -316
  64. data/lib/puma/request.rb +476 -0
  65. data/lib/puma/runner.rb +48 -55
  66. data/lib/puma/server.rb +305 -695
  67. data/lib/puma/single.rb +11 -67
  68. data/lib/puma/state_file.rb +48 -8
  69. data/lib/puma/systemd.rb +46 -0
  70. data/lib/puma/thread_pool.rb +132 -82
  71. data/lib/puma/util.rb +33 -10
  72. data/lib/puma.rb +56 -0
  73. data/lib/rack/handler/puma.rb +5 -6
  74. data/lib/rack/version_restriction.rb +15 -0
  75. data/tools/Dockerfile +16 -0
  76. data/tools/trickletest.rb +0 -1
  77. metadata +46 -29
  78. data/ext/puma_http11/io_buffer.c +0 -155
  79. data/lib/puma/accept_nonblock.rb +0 -23
  80. data/lib/puma/compat.rb +0 -14
  81. data/lib/puma/convenient.rb +0 -25
  82. data/lib/puma/daemon_ext.rb +0 -33
  83. data/lib/puma/delegation.rb +0 -13
  84. data/lib/puma/java_io_buffer.rb +0 -47
  85. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
  86. data/lib/puma/tcp_logger.rb +0 -41
  87. data/tools/jungle/README.md +0 -19
  88. data/tools/jungle/init.d/README.md +0 -61
  89. data/tools/jungle/init.d/puma +0 -421
  90. data/tools/jungle/init.d/run-puma +0 -18
  91. data/tools/jungle/upstart/README.md +0 -61
  92. data/tools/jungle/upstart/puma-manager.conf +0 -31
  93. data/tools/jungle/upstart/puma.conf +0 -69
  94. /data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
data/lib/puma/dsl.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'puma/const'
4
+ require 'puma/util'
5
+
3
6
  module Puma
4
- # The methods that are available for use inside the config file.
7
+ # The methods that are available for use inside the configuration file.
5
8
  # These same methods are used in Puma cli and the rack handler
6
9
  # internally.
7
10
  #
@@ -12,24 +15,65 @@ module Puma
12
15
  # end
13
16
  # config.load
14
17
  #
15
- # puts config.options[:binds]
16
- # "tcp://127.0.0.1:3001"
18
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3001"
17
19
  #
18
20
  # Used to load file:
19
21
  #
20
22
  # $ cat puma_config.rb
21
- # port 3002
23
+ # port 3002
24
+ #
25
+ # Resulting configuration:
22
26
  #
23
27
  # config = Configuration.new(config_file: "puma_config.rb")
24
28
  # config.load
25
29
  #
26
- # puts config.options[:binds]
27
- # # => "tcp://127.0.0.1:3002"
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+.
28
34
  #
29
- # Detailed docs can be found in `examples/config.rb`
30
35
  class DSL
31
36
  include ConfigDefault
32
37
 
38
+ # convenience method so logic can be used in CI
39
+ # @see ssl_bind
40
+ #
41
+ def self.ssl_bind_str(host, port, opts)
42
+ verify = opts.fetch(:verify_mode, 'none').to_s
43
+
44
+ tls_str =
45
+ if opts[:no_tlsv1_1] then '&no_tlsv1_1=true'
46
+ elsif opts[:no_tlsv1] then '&no_tlsv1=true'
47
+ else ''
48
+ end
49
+
50
+ ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
51
+
52
+ backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
53
+
54
+ if defined?(JRUBY_VERSION)
55
+ ssl_cipher_list = opts[:ssl_cipher_list] ?
56
+ "&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
57
+
58
+ keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
59
+
60
+ "ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
61
+ "&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
62
+ else
63
+ ssl_cipher_filter = opts[:ssl_cipher_filter] ?
64
+ "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
65
+
66
+ v_flags = (ary = opts[:verification_flags]) ?
67
+ "&verification_flags=#{Array(ary).join ','}" : nil
68
+
69
+ cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(opts[:cert])}" : nil
70
+ key_flags = (cert = opts[:key]) ? "&key=#{Puma::Util.escape(opts[:key])}" : nil
71
+
72
+ "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}" \
73
+ "#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
74
+ end
75
+ end
76
+
33
77
  def initialize(options, config)
34
78
  @config = config
35
79
  @options = options
@@ -79,8 +123,24 @@ module Puma
79
123
  @plugins << @config.load_plugin(name)
80
124
  end
81
125
 
82
- # Use +obj+ or +block+ as the Rack app. This allows a config file to
83
- # be the app itself.
126
+ # Use an object or block as the rack application. This allows the
127
+ # configuration file to be the application itself.
128
+ #
129
+ # @example
130
+ # app do |env|
131
+ # body = 'Hello, World!'
132
+ #
133
+ # [
134
+ # 200,
135
+ # {
136
+ # 'Content-Type' => 'text/plain',
137
+ # 'Content-Length' => body.length.to_s
138
+ # },
139
+ # [body]
140
+ # ]
141
+ # end
142
+ #
143
+ # @see Puma::Configuration#app
84
144
  #
85
145
  def app(obj=nil, &block)
86
146
  obj ||= block
@@ -90,9 +150,20 @@ module Puma
90
150
  @options[:app] = obj
91
151
  end
92
152
 
93
- # Start the Puma control rack app on +url+. This app can be communicated
94
- # with to control the main server.
153
+ # Start the Puma control rack application on +url+. This application can
154
+ # be communicated with to control the main server. Additionally, you can
155
+ # provide an authentication token, so all requests to the control server
156
+ # will need to include that token as a query parameter. This allows for
157
+ # simple authentication.
158
+ #
159
+ # Check out {Puma::App::Status} to see what the app has available.
95
160
  #
161
+ # @example
162
+ # activate_control_app 'unix:///var/run/pumactl.sock'
163
+ # @example
164
+ # activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
165
+ # @example
166
+ # activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
96
167
  def activate_control_app(url="auto", opts={})
97
168
  if url == "auto"
98
169
  path = Configuration.temp_path
@@ -103,7 +174,12 @@ module Puma
103
174
  end
104
175
 
105
176
  if opts[:no_token]
106
- auth_token = :none
177
+ # We need to use 'none' rather than :none because this value will be
178
+ # passed on to an instance of OptionParser, which doesn't support
179
+ # symbols as option values.
180
+ #
181
+ # See: https://github.com/puma/puma/issues/1193#issuecomment-305995488
182
+ auth_token = 'none'
107
183
  else
108
184
  auth_token = opts[:auth_token]
109
185
  auth_token ||= Configuration.random_token
@@ -120,22 +196,32 @@ module Puma
120
196
  @options[:config_files] << file
121
197
  end
122
198
 
123
- # Adds a binding for the server to +url+. tcp://, unix://, and ssl:// are the only accepted
124
- # protocols. Use query parameters within the url to specify options.
199
+ # Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
200
+ # accepted protocols. Multiple urls can be bound to, calling +bind+ does
201
+ # not overwrite previous bindings.
125
202
  #
126
- # @note multiple urls can be bound to, calling `bind` does not overwrite previous bindings.
203
+ # The default is "tcp://0.0.0.0:9292".
127
204
  #
128
- # @example Explicitly the socket backlog depth (default is 1024)
129
- # bind('unix:///var/run/puma.sock?backlog=2048')
205
+ # You can use query parameters within the url to specify options:
130
206
  #
131
- # @example Set up ssl cert
132
- # bind('ssl://127.0.0.1:9292?key=key.key&cert=cert.pem')
207
+ # * Set the socket backlog depth with +backlog+, default is 1024.
208
+ # * Set up an SSL certificate with +key+ & +cert+.
209
+ # * Set whether to optimize for low latency instead of throughput with
210
+ # +low_latency+, default is to not optimize for low latency. This is done
211
+ # via +Socket::TCP_NODELAY+.
212
+ # * Set socket permissions with +umask+.
133
213
  #
134
- # @example Prefer low-latency over higher throughput (via `Socket::TCP_NODELAY`)
135
- # bind('tcp://0.0.0.0:9292?low_latency=true')
214
+ # @example Backlog depth
215
+ # bind 'unix:///var/run/puma.sock?backlog=512'
216
+ # @example SSL cert
217
+ # bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
218
+ # @example Disable optimization for low latency
219
+ # bind 'tcp://0.0.0.0:9292?low_latency=false'
220
+ # @example Socket permissions
221
+ # bind 'unix:///var/run/puma.sock?umask=0111'
222
+ # @see Puma::Runner#load_and_bind
223
+ # @see Puma::Cluster#run
136
224
  #
137
- # @example Set socket permissions
138
- # bind('unix:///var/run/puma.sock?umask=0111')
139
225
  def bind(url)
140
226
  @options[:binds] ||= []
141
227
  @options[:binds] << url
@@ -145,48 +231,75 @@ module Puma
145
231
  @options[:binds] = []
146
232
  end
147
233
 
234
+ # Bind to (systemd) activated sockets, regardless of configured binds.
235
+ #
236
+ # Systemd can present sockets as file descriptors that are already opened.
237
+ # By default Puma will use these but only if it was explicitly told to bind
238
+ # to the socket. If not, it will close the activated sockets. This means
239
+ # all configuration is duplicated.
240
+ #
241
+ # Binds can contain additional configuration, but only SSL config is really
242
+ # relevant since the unix and TCP socket options are ignored.
243
+ #
244
+ # This means there is a lot of duplicated configuration for no additional
245
+ # value in most setups. This method tells the launcher to bind to all
246
+ # activated sockets, regardless of existing bind.
247
+ #
248
+ # To clear configured binds, the value only can be passed. This will clear
249
+ # out any binds that may have been configured.
250
+ #
251
+ # @example Use any systemd activated sockets as well as configured binds
252
+ # bind_to_activated_sockets
253
+ #
254
+ # @example Only bind to systemd activated sockets, ignoring other binds
255
+ # bind_to_activated_sockets 'only'
256
+ def bind_to_activated_sockets(bind=true)
257
+ @options[:bind_to_activated_sockets] = bind
258
+ end
259
+
148
260
  # Define the TCP port to bind to. Use +bind+ for more advanced options.
149
261
  #
262
+ # @example
263
+ # port 9292
150
264
  def port(port, host=nil)
151
265
  host ||= default_host
152
- bind "tcp://#{host}:#{port}"
266
+ bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
153
267
  end
154
268
 
155
- # Define how long persistent connections can be idle before puma closes
156
- # them
157
- #
269
+ # Define how long persistent connections can be idle before Puma closes them.
270
+ # @see Puma::Server.new
158
271
  def persistent_timeout(seconds)
159
272
  @options[:persistent_timeout] = Integer(seconds)
160
273
  end
161
274
 
162
- # Define how long the tcp socket stays open, if no data has been received
163
- #
275
+ # Define how long the tcp socket stays open, if no data has been received.
276
+ # @see Puma::Server.new
164
277
  def first_data_timeout(seconds)
165
278
  @options[:first_data_timeout] = Integer(seconds)
166
279
  end
167
280
 
168
281
  # Work around leaky apps that leave garbage in Thread locals
169
- # across requests
170
- #
282
+ # across requests.
171
283
  def clean_thread_locals(which=true)
172
284
  @options[:clean_thread_locals] = which
173
285
  end
174
286
 
175
- # Daemonize the server into the background. Highly suggest that
176
- # this be combined with +pidfile+ and +stdout_redirect+.
177
- def daemonize(which=true)
178
- @options[:daemon] = which
179
- end
180
-
181
- # When shutting down, drain the accept socket of pending
182
- # connections and process them. This loops over the accept
183
- # socket until there are no more read events and then stops
184
- # looking and waits for the requests to finish.
287
+ # When shutting down, drain the accept socket of pending connections and
288
+ # process them. This loops over the accept socket until there are no more
289
+ # read events and then stops looking and waits for the requests to finish.
290
+ # @see Puma::Server#graceful_shutdown
291
+ #
185
292
  def drain_on_shutdown(which=true)
186
293
  @options[:drain_on_shutdown] = which
187
294
  end
188
295
 
189
- # Set the environment in which the Rack's app will run.
296
+ # Set the environment in which the rack's app will run. The value must be
297
+ # a string.
298
+ #
299
+ # The default is "development".
300
+ #
301
+ # @example
302
+ # environment 'production'
190
303
  def environment(environment)
191
304
  @options[:environment] = environment
192
305
  end
@@ -198,6 +311,7 @@ module Puma
198
311
  #
199
312
  # Puma always waits a few seconds after killing a thread for it to try
200
313
  # to finish up it's work, even in :immediately mode.
314
+ # @see Puma::Server#graceful_shutdown
201
315
  def force_shutdown_after(val=:forever)
202
316
  i = case val
203
317
  when :forever
@@ -205,37 +319,48 @@ module Puma
205
319
  when :immediately
206
320
  0
207
321
  else
208
- Integer(val)
322
+ Float(val)
209
323
  end
210
324
 
211
325
  @options[:force_shutdown_after] = i
212
326
  end
213
327
 
214
328
  # Code to run before doing a restart. This code should
215
- # close logfiles, database connections, etc.
329
+ # close log files, database connections, etc.
216
330
  #
217
331
  # This can be called multiple times to add code each time.
218
332
  #
333
+ # @example
334
+ # on_restart do
335
+ # puts 'On restart...'
336
+ # end
219
337
  def on_restart(&block)
220
338
  @options[:on_restart] ||= []
221
339
  @options[:on_restart] << block
222
340
  end
223
341
 
224
- # Command to use to restart puma. This should be just how to
225
- # load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
226
- # to puma, as those are the same as the original process.
342
+ # Command to use to restart Puma. This should be just how to
343
+ # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
344
+ # to Puma, as those are the same as the original process.
227
345
  #
346
+ # @example
347
+ # restart_command '/u/app/lolcat/bin/restart_puma'
228
348
  def restart_command(cmd)
229
349
  @options[:restart_cmd] = cmd.to_s
230
350
  end
231
351
 
232
- # Store the pid of the server in the file at +path+.
352
+ # Store the pid of the server in the file at "path".
353
+ #
354
+ # @example
355
+ # pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
233
356
  def pidfile(path)
234
357
  @options[:pidfile] = path.to_s
235
358
  end
236
359
 
237
- # Disable request logging.
360
+ # Disable request logging, if this isn't used it'll be enabled by default.
238
361
  #
362
+ # @example
363
+ # quiet
239
364
  def quiet(which=true)
240
365
  @options[:log_requests] = !which
241
366
  end
@@ -254,30 +379,54 @@ module Puma
254
379
 
255
380
  # Load +path+ as a rackup file.
256
381
  #
382
+ # The default is "config.ru".
383
+ #
384
+ # @example
385
+ # rackup '/u/apps/lolcat/config.ru'
257
386
  def rackup(path)
258
- @options[:rackup] = path.to_s
387
+ @options[:rackup] ||= path.to_s
259
388
  end
260
389
 
261
- # Run Puma in TCP mode
262
- #
263
- def tcp_mode!
264
- @options[:mode] = :tcp
390
+ # Allows setting `env['rack.url_scheme']`.
391
+ # Only necessary if X-Forwarded-Proto is not being set by your proxy
392
+ # Normal values are 'http' or 'https'.
393
+ def rack_url_scheme(scheme=nil)
394
+ @options[:rack_url_scheme] = scheme
265
395
  end
266
396
 
267
397
  def early_hints(answer=true)
268
398
  @options[:early_hints] = answer
269
399
  end
270
400
 
271
- # Redirect STDOUT and STDERR to files specified.
401
+ # Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
402
+ # specifies whether the output is appended, the default is +false+.
403
+ #
404
+ # @example
405
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
406
+ # @example
407
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
272
408
  def stdout_redirect(stdout=nil, stderr=nil, append=false)
273
409
  @options[:redirect_stdout] = stdout
274
410
  @options[:redirect_stderr] = stderr
275
411
  @options[:redirect_append] = append
276
412
  end
277
413
 
414
+ def log_formatter(&block)
415
+ @options[:log_formatter] = block
416
+ end
417
+
278
418
  # Configure +min+ to be the minimum number of threads to use to answer
279
419
  # requests and +max+ the maximum.
280
420
  #
421
+ # The default is the environment variables +PUMA_MIN_THREADS+ / +PUMA_MAX_THREADS+
422
+ # (or +MIN_THREADS+ / +MAX_THREADS+ if the +PUMA_+ variables aren't set).
423
+ #
424
+ # If these environment variables aren't set, the default is "0, 5" in MRI or "0, 16" for other interpreters.
425
+ #
426
+ # @example
427
+ # threads 0, 16
428
+ # @example
429
+ # threads 5, 5
281
430
  def threads(min, max)
282
431
  min = Integer(min)
283
432
  max = Integer(max)
@@ -293,115 +442,242 @@ module Puma
293
442
  @options[:max_threads] = max
294
443
  end
295
444
 
296
- def ssl_bind(host, port, opts)
297
- verify = opts.fetch(:verify_mode, 'none')
298
-
299
- if defined?(JRUBY_VERSION)
300
- keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
301
- bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}"
302
- else
303
- bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&verify_mode=#{verify}"
304
- end
445
+ # Instead of using +bind+ and manually constructing a URI like:
446
+ #
447
+ # bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
448
+ #
449
+ # you can use the this method.
450
+ #
451
+ # When binding on localhost you don't need to specify +cert+ and +key+,
452
+ # Puma will assume you are using the +localhost+ gem and try to load the
453
+ # appropriate files.
454
+ #
455
+ # @example
456
+ # ssl_bind '127.0.0.1', '9292', {
457
+ # cert: path_to_cert,
458
+ # key: path_to_key,
459
+ # ssl_cipher_filter: cipher_filter, # optional
460
+ # verify_mode: verify_mode, # default 'none'
461
+ # verification_flags: flags, # optional, not supported by JRuby
462
+ # }
463
+ #
464
+ # @example Using self-signed certificate with the +localhost+ gem:
465
+ # ssl_bind '127.0.0.1', '9292'
466
+ #
467
+ # @example Alternatively, you can provide +cert_pem+ and +key_pem+:
468
+ # ssl_bind '127.0.0.1', '9292', {
469
+ # cert_pem: File.read(path_to_cert),
470
+ # key_pem: File.read(path_to_key),
471
+ # }
472
+ #
473
+ # @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
474
+ # ssl_bind '127.0.0.1', '9292', {
475
+ # keystore: path_to_keystore,
476
+ # keystore_pass: password,
477
+ # ssl_cipher_list: cipher_list, # optional
478
+ # verify_mode: verify_mode # default 'none'
479
+ # }
480
+ def ssl_bind(host, port, opts = {})
481
+ add_pem_values_to_options_store(opts)
482
+ bind self.class.ssl_bind_str(host, port, opts)
305
483
  end
306
484
 
307
485
  # Use +path+ as the file to store the server info state. This is
308
- # used by pumactl to query and control the server.
486
+ # used by +pumactl+ to query and control the server.
309
487
  #
488
+ # @example
489
+ # state_path '/u/apps/lolcat/tmp/pids/puma.state'
310
490
  def state_path(path)
311
491
  @options[:state] = path.to_s
312
492
  end
313
493
 
314
- # *Cluster mode only* How many worker processes to run.
494
+ # Use +permission+ to restrict permissions for the state file.
495
+ #
496
+ # @example
497
+ # state_permission 0600
498
+ # @version 5.0.0
499
+ #
500
+ def state_permission(permission)
501
+ @options[:state_permission] = permission
502
+ end
503
+
504
+ # How many worker processes to run. Typically this is set to
505
+ # the number of available cores.
315
506
  #
507
+ # The default is the value of the environment variable +WEB_CONCURRENCY+ if
508
+ # set, otherwise 0.
509
+ #
510
+ # @note Cluster mode only.
511
+ # @see Puma::Cluster
316
512
  def workers(count)
317
513
  @options[:workers] = count.to_i
318
514
  end
319
515
 
320
- # *Cluster mode only* Code to run immediately before master process
516
+ # Disable warning message when running in cluster mode with a single worker.
517
+ #
518
+ # Cluster mode has some overhead of running an additional 'control' process
519
+ # in order to manage the cluster. If only running a single worker it is
520
+ # likely not worth paying that overhead vs running in single mode with
521
+ # additional threads instead.
522
+ #
523
+ # There are some scenarios where running cluster mode with a single worker
524
+ # may still be warranted and valid under certain deployment scenarios, see
525
+ # https://github.com/puma/puma/issues/2534
526
+ #
527
+ # Moving from workers = 1 to workers = 0 will save 10-30% of memory use.
528
+ #
529
+ # @note Cluster mode only.
530
+ def silence_single_worker_warning
531
+ @options[:silence_single_worker_warning] = true
532
+ end
533
+
534
+ # Code to run immediately before master process
321
535
  # forks workers (once on boot). These hooks can block if necessary
322
- # to wait for background operations unknown to puma to finish before
536
+ # to wait for background operations unknown to Puma to finish before
323
537
  # the process terminates.
324
- # This can be used to close any connections to remote servers (database, redis, ...)
325
- # that were opened when preloading the code
538
+ # This can be used to close any connections to remote servers (database,
539
+ # Redis, ...) that were opened when preloading the code.
326
540
  #
327
- # This can be called multiple times to add hooks.
541
+ # This can be called multiple times to add several hooks.
328
542
  #
543
+ # @note Cluster mode only.
544
+ # @example
545
+ # before_fork do
546
+ # puts "Starting workers..."
547
+ # end
329
548
  def before_fork(&block)
330
549
  @options[:before_fork] ||= []
331
550
  @options[:before_fork] << block
332
551
  end
333
552
 
334
- # *Cluster mode only* Code to run in a worker when it boots to setup
553
+ # Code to run in a worker when it boots to setup
335
554
  # the process before booting the app.
336
555
  #
337
- # This can be called multiple times to add hooks.
556
+ # This can be called multiple times to add several hooks.
338
557
  #
558
+ # @note Cluster mode only.
559
+ # @example
560
+ # on_worker_boot do
561
+ # puts 'Before worker boot...'
562
+ # end
339
563
  def on_worker_boot(&block)
340
564
  @options[:before_worker_boot] ||= []
341
565
  @options[:before_worker_boot] << block
342
566
  end
343
567
 
344
- # *Cluster mode only* Code to run immediately before a worker shuts
568
+ # Code to run immediately before a worker shuts
345
569
  # down (after it has finished processing HTTP requests). These hooks
346
570
  # can block if necessary to wait for background operations unknown
347
- # to puma to finish before the process terminates.
571
+ # to Puma to finish before the process terminates.
348
572
  #
349
- # This can be called multiple times to add hooks.
573
+ # This can be called multiple times to add several hooks.
350
574
  #
575
+ # @note Cluster mode only.
576
+ # @example
577
+ # on_worker_shutdown do
578
+ # puts 'On worker shutdown...'
579
+ # end
351
580
  def on_worker_shutdown(&block)
352
581
  @options[:before_worker_shutdown] ||= []
353
582
  @options[:before_worker_shutdown] << block
354
583
  end
355
584
 
356
- # *Cluster mode only* Code to run in the master when it is
357
- # about to create the worker by forking itself.
585
+ # Code to run in the master right before a worker is started. The worker's
586
+ # index is passed as an argument.
358
587
  #
359
- # This can be called multiple times to add hooks.
588
+ # This can be called multiple times to add several hooks.
360
589
  #
590
+ # @note Cluster mode only.
591
+ # @example
592
+ # on_worker_fork do
593
+ # puts 'Before worker fork...'
594
+ # end
361
595
  def on_worker_fork(&block)
362
596
  @options[:before_worker_fork] ||= []
363
597
  @options[:before_worker_fork] << block
364
598
  end
365
599
 
366
- # *Cluster mode only* Code to run in the master after it starts
367
- # a worker.
600
+ # Code to run in the master after a worker has been started. The worker's
601
+ # index is passed as an argument.
368
602
  #
369
- # This can be called multiple times to add hooks.
603
+ # This is called everytime a worker is to be started.
370
604
  #
605
+ # @note Cluster mode only.
606
+ # @example
607
+ # after_worker_fork do
608
+ # puts 'After worker fork...'
609
+ # end
371
610
  def after_worker_fork(&block)
372
611
  @options[:after_worker_fork] ||= []
373
- @options[:after_worker_fork] = block
612
+ @options[:after_worker_fork] << block
374
613
  end
375
614
 
376
615
  alias_method :after_worker_boot, :after_worker_fork
377
616
 
378
- # The directory to operate out of.
379
- def directory(dir)
380
- @options[:directory] = dir.to_s
617
+ # When `fork_worker` is enabled, code to run in Worker 0
618
+ # before all other workers are re-forked from this process,
619
+ # after the server has temporarily stopped serving requests
620
+ # (once per complete refork cycle).
621
+ #
622
+ # This can be used to trigger extra garbage-collection to maximize
623
+ # copy-on-write efficiency, or close any connections to remote servers
624
+ # (database, Redis, ...) that were opened while the server was running.
625
+ #
626
+ # This can be called multiple times to add several hooks.
627
+ #
628
+ # @note Cluster mode with `fork_worker` enabled only.
629
+ # @example
630
+ # on_refork do
631
+ # 3.times {GC.start}
632
+ # end
633
+ # @version 5.0.0
634
+ #
635
+ def on_refork(&block)
636
+ @options[:before_refork] ||= []
637
+ @options[:before_refork] << block
381
638
  end
382
639
 
383
- # DEPRECATED: The directory to operate out of.
384
- def worker_directory(dir)
385
- $stderr.puts "worker_directory is deprecated. Please use `directory`"
386
- directory dir
640
+ # Code to run out-of-band when the worker is idle.
641
+ # These hooks run immediately after a request has finished
642
+ # processing and there are no busy threads on the worker.
643
+ # The worker doesn't accept new requests until this code finishes.
644
+ #
645
+ # This hook is useful for running out-of-band garbage collection
646
+ # or scheduling asynchronous tasks to execute after a response.
647
+ #
648
+ # This can be called multiple times to add several hooks.
649
+ def out_of_band(&block)
650
+ @options[:out_of_band] ||= []
651
+ @options[:out_of_band] << block
387
652
  end
388
653
 
389
- # Run the app as a raw TCP app instead of an HTTP rack app
390
- def tcp_mode
391
- @options[:mode] = :tcp
654
+ # The directory to operate out of.
655
+ #
656
+ # The default is the current directory.
657
+ #
658
+ # @example
659
+ # directory '/u/apps/lolcat'
660
+ def directory(dir)
661
+ @options[:directory] = dir.to_s
392
662
  end
393
663
 
394
- # *Cluster mode only* Preload the application before starting
395
- # the workers and setting up the listen ports. This conflicts
396
- # with using the phased restart feature, you can't use both.
664
+ # Preload the application before starting the workers; this conflicts with
665
+ # phased restart feature. On by default if your app uses more than 1 worker.
397
666
  #
667
+ # @note Cluster mode only.
668
+ # @example
669
+ # preload_app!
398
670
  def preload_app!(answer=true)
399
671
  @options[:preload_app] = answer
400
672
  end
401
673
 
402
- # Use +obj+ or +block+ as the low level error handler. This allows a config file to
403
- # change the default error on the server.
674
+ # Use +obj+ or +block+ as the low level error handler. This allows the
675
+ # configuration file to change the default error on the server.
404
676
  #
677
+ # @example
678
+ # lowlevel_error_handler do |err|
679
+ # [200, {}, ["error page"]]
680
+ # end
405
681
  def lowlevel_error_handler(obj=nil, &block)
406
682
  obj ||= block
407
683
  raise "Provide either a #call'able or a block" unless obj
@@ -411,42 +687,153 @@ module Puma
411
687
  # This option is used to allow your app and its gems to be
412
688
  # properly reloaded when not using preload.
413
689
  #
414
- # When set, if puma detects that it's been invoked in the
690
+ # When set, if Puma detects that it's been invoked in the
415
691
  # context of Bundler, it will cleanup the environment and
416
692
  # re-run itself outside the Bundler environment, but directly
417
693
  # using the files that Bundler has setup.
418
694
  #
419
- # This means that puma is now decoupled from your Bundler
695
+ # This means that Puma is now decoupled from your Bundler
420
696
  # context and when each worker loads, it will be loading a
421
697
  # new Bundler context and thus can float around as the release
422
698
  # dictates.
699
+ #
700
+ # @see extra_runtime_dependencies
701
+ #
702
+ # @note This is incompatible with +preload_app!+.
703
+ # @note This is only supported for RubyGems 2.2+
423
704
  def prune_bundler(answer=true)
424
705
  @options[:prune_bundler] = answer
425
706
  end
426
707
 
427
- # Additional text to display in process listing
708
+ # By default, Puma will raise SignalException when SIGTERM is received. In
709
+ # environments where SIGTERM is something expected, you can suppress these
710
+ # with this option.
711
+ #
712
+ # This can be useful for example in Kubernetes, where rolling restart is
713
+ # guaranteed usually on infrastructure level.
714
+ #
715
+ # @example
716
+ # raise_exception_on_sigterm false
717
+ # @see Puma::Launcher#setup_signals
718
+ # @see Puma::Cluster#setup_signals
719
+ #
720
+ def raise_exception_on_sigterm(answer=true)
721
+ @options[:raise_exception_on_sigterm] = answer
722
+ end
723
+
724
+ # When using prune_bundler, if extra runtime dependencies need to be loaded to
725
+ # initialize your app, then this setting can be used. This includes any Puma plugins.
726
+ #
727
+ # Before bundler is pruned, the gem names supplied will be looked up in the bundler
728
+ # context and then loaded again after bundler is pruned.
729
+ # Only applies if prune_bundler is used.
730
+ #
731
+ # @example
732
+ # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
733
+ # @example
734
+ # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
735
+ # @see Puma::Launcher#extra_runtime_deps_directories
736
+ #
737
+ def extra_runtime_dependencies(answer = [])
738
+ @options[:extra_runtime_dependencies] = Array(answer)
739
+ end
740
+
741
+ # Additional text to display in process listing.
742
+ #
743
+ # If you do not specify a tag, Puma will infer it. If you do not want Puma
744
+ # to add a tag, use an empty string.
745
+ #
746
+ # @example
747
+ # tag 'app name'
748
+ # @example
749
+ # tag ''
428
750
  def tag(string)
429
751
  @options[:tag] = string.to_s
430
752
  end
431
753
 
432
- # *Cluster mode only* Set the timeout for workers in seconds
433
- # When set the master process will terminate any workers
434
- # that have not checked in within the given +timeout+.
435
- # This mitigates hung processes. Default value is 60 seconds.
754
+ # Change the default interval for checking workers.
755
+ #
756
+ # The default value is 5 seconds.
757
+ #
758
+ # @note Cluster mode only.
759
+ # @example
760
+ # worker_check_interval 5
761
+ # @see Puma::Cluster#check_workers
762
+ #
763
+ def worker_check_interval(interval)
764
+ @options[:worker_check_interval] = Integer(interval)
765
+ end
766
+
767
+ # Verifies that all workers have checked in to the master process within
768
+ # the given timeout. If not the worker process will be restarted. This is
769
+ # not a request timeout, it is to protect against a hung or dead process.
770
+ # Setting this value will not protect against slow requests.
771
+ #
772
+ # The minimum value is 6 seconds, the default value is 60 seconds.
773
+ #
774
+ # @note Cluster mode only.
775
+ # @example
776
+ # worker_timeout 60
777
+ # @see Puma::Cluster::Worker#ping_timeout
778
+ #
436
779
  def worker_timeout(timeout)
437
- @options[:worker_timeout] = Integer(timeout)
780
+ timeout = Integer(timeout)
781
+ min = @options.fetch(:worker_check_interval, Puma::ConfigDefault::DefaultWorkerCheckInterval)
782
+
783
+ if timeout <= min
784
+ raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
785
+ end
786
+
787
+ @options[:worker_timeout] = timeout
438
788
  end
439
789
 
440
- # *Cluster mode only* Set the timeout for workers to boot
790
+ # Change the default worker timeout for booting.
791
+ #
792
+ # If unspecified, this defaults to the value of worker_timeout.
793
+ #
794
+ # @note Cluster mode only.
795
+ #
796
+ # @example
797
+ # worker_boot_timeout 60
798
+ # @see Puma::Cluster::Worker#ping_timeout
799
+ #
441
800
  def worker_boot_timeout(timeout)
442
801
  @options[:worker_boot_timeout] = Integer(timeout)
443
802
  end
444
803
 
445
- # *Cluster mode only* Set the timeout for worker shutdown
804
+ # Set the timeout for worker shutdown.
805
+ #
806
+ # @note Cluster mode only.
807
+ # @see Puma::Cluster::Worker#term
808
+ #
446
809
  def worker_shutdown_timeout(timeout)
447
810
  @options[:worker_shutdown_timeout] = Integer(timeout)
448
811
  end
449
812
 
813
+ # Set the strategy for worker culling.
814
+ #
815
+ # There are two possible values:
816
+ #
817
+ # 1. **:youngest** - the youngest workers (i.e. the workers that were
818
+ # the most recently started) will be culled.
819
+ # 2. **:oldest** - the oldest workers (i.e. the workers that were started
820
+ # the longest time ago) will be culled.
821
+ #
822
+ # @note Cluster mode only.
823
+ # @example
824
+ # worker_culling_strategy :oldest
825
+ # @see Puma::Cluster#cull_workers
826
+ #
827
+ def worker_culling_strategy(strategy)
828
+ stategy = strategy.to_sym
829
+
830
+ if ![:youngest, :oldest].include?(strategy)
831
+ raise "Invalid value for worker_culling_strategy - #{stategy}"
832
+ end
833
+
834
+ @options[:worker_culling_strategy] = strategy
835
+ end
836
+
450
837
  # When set to true (the default), workers accept all requests
451
838
  # and queue them before passing them to the handlers.
452
839
  # When set to false, each worker process accepts exactly as
@@ -459,7 +846,8 @@ module Puma
459
846
  # Note that setting this to false disables HTTP keepalive and
460
847
  # slow clients will occupy a handler thread while the request
461
848
  # is being sent. A reverse proxy, such as nginx, can handle
462
- # slow clients and queue requests before they reach puma.
849
+ # slow clients and queue requests before they reach Puma.
850
+ # @see Puma::Server
463
851
  def queue_requests(answer=true)
464
852
  @options[:queue_requests] = answer
465
853
  end
@@ -467,29 +855,47 @@ module Puma
467
855
  # When a shutdown is requested, the backtraces of all the
468
856
  # threads will be written to $stdout. This can help figure
469
857
  # out why shutdown is hanging.
858
+ #
470
859
  def shutdown_debug(val=true)
471
860
  @options[:shutdown_debug] = val
472
861
  end
473
862
 
863
+
864
+ # Attempts to route traffic to less-busy workers by causing them to delay
865
+ # listening on the socket, allowing workers which are not processing any
866
+ # requests to pick up new requests first.
867
+ #
868
+ # Only works on MRI. For all other interpreters, this setting does nothing.
869
+ # @see Puma::Server#handle_servers
870
+ # @see Puma::ThreadPool#wait_for_less_busy_worker
871
+ # @version 5.0.0
872
+ #
873
+ def wait_for_less_busy_worker(val=0.005)
874
+ @options[:wait_for_less_busy_worker] = val.to_f
875
+ end
876
+
474
877
  # Control how the remote address of the connection is set. This
475
878
  # is configurable because to calculate the true socket peer address
476
879
  # a kernel syscall is required which for very fast rack handlers
477
880
  # slows down the handling significantly.
478
881
  #
479
- # There are 4 possible values:
480
- #
481
- # * :socket (the default) - read the peername from the socket using the
482
- # syscall. This is the normal behavior.
483
- # * :localhost - set the remote address to "127.0.0.1"
484
- # * header: http_header - set the remote address to the value of the
485
- # provided http header. For instance:
486
- # `set_remote_address header: "X-Real-IP"`.
487
- # Only the first word (as separated by spaces or comma)
488
- # is used, allowing headers such as X-Forwarded-For
489
- # to be used as well.
490
- # * Any string - this allows you to hardcode remote address to any value
491
- # you wish. Because puma never uses this field anyway, it's
492
- # format is entirely in your hands.
882
+ # There are 5 possible values:
883
+ #
884
+ # 1. **:socket** (the default) - read the peername from the socket using the
885
+ # syscall. This is the normal behavior.
886
+ # 2. **:localhost** - set the remote address to "127.0.0.1"
887
+ # 3. **header: <http_header>**- set the remote address to the value of the
888
+ # provided http header. For instance:
889
+ # `set_remote_address header: "X-Real-IP"`.
890
+ # Only the first word (as separated by spaces or comma) is used, allowing
891
+ # headers such as X-Forwarded-For to be used as well.
892
+ # 4. **proxy_protocol: :v1**- set the remote address to the value read from the
893
+ # HAproxy PROXY protocol, version 1. If the request does not have the PROXY
894
+ # protocol attached to it, will fall back to :socket
895
+ # 5. **\<Any string\>** - this allows you to hardcode remote address to any value
896
+ # you wish. Because Puma never uses this field anyway, it's format is
897
+ # entirely in your hands.
898
+ #
493
899
  def set_remote_address(val=:socket)
494
900
  case val
495
901
  when :socket
@@ -504,6 +910,13 @@ module Puma
504
910
  if hdr = val[:header]
505
911
  @options[:remote_address] = :header
506
912
  @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
913
+ elsif protocol_version = val[:proxy_protocol]
914
+ @options[:remote_address] = :proxy_protocol
915
+ protocol_version = protocol_version.downcase.to_sym
916
+ unless [:v1].include?(protocol_version)
917
+ raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
918
+ end
919
+ @options[:remote_address_proxy_protocol] = protocol_version
507
920
  else
508
921
  raise "Invalid value for set_remote_address - #{val.inspect}"
509
922
  end
@@ -512,5 +925,88 @@ module Puma
512
925
  end
513
926
  end
514
927
 
928
+ # When enabled, workers will be forked from worker 0 instead of from the master process.
929
+ # This option is similar to `preload_app` because the app is preloaded before forking,
930
+ # but it is compatible with phased restart.
931
+ #
932
+ # This option also enables the `refork` command (SIGURG), which optimizes copy-on-write performance
933
+ # in a running app.
934
+ #
935
+ # A refork will automatically trigger once after the specified number of requests
936
+ # (default 1000), or pass 0 to disable auto refork.
937
+ #
938
+ # @note Cluster mode only.
939
+ # @version 5.0.0
940
+ #
941
+ def fork_worker(after_requests=1000)
942
+ @options[:fork_worker] = Integer(after_requests)
943
+ end
944
+
945
+ # When enabled, Puma will GC 4 times before forking workers.
946
+ # If available (Ruby 2.7+), we will also call GC.compact.
947
+ # Not recommended for non-MRI Rubies.
948
+ #
949
+ # Based on the work of Koichi Sasada and Aaron Patterson, this option may
950
+ # decrease memory utilization of preload-enabled cluster-mode Pumas. It will
951
+ # also increase time to boot and fork. See your logs for details on how much
952
+ # time this adds to your boot process. For most apps, it will be less than one
953
+ # second.
954
+ #
955
+ # @see Puma::Cluster#nakayoshi_gc
956
+ # @version 5.0.0
957
+ #
958
+ def nakayoshi_fork(enabled=true)
959
+ @options[:nakayoshi_fork] = enabled
960
+ end
961
+
962
+ # The number of requests to attempt inline before sending a client back to
963
+ # the reactor to be subject to normal ordering.
964
+ #
965
+ def max_fast_inline(num_of_requests)
966
+ @options[:max_fast_inline] = Float(num_of_requests)
967
+ end
968
+
969
+ # Specify the backend for the IO selector.
970
+ #
971
+ # Provided values will be passed directly to +NIO::Selector.new+, with the
972
+ # exception of +:auto+ which will let nio4r choose the backend.
973
+ #
974
+ # Check the documentation of +NIO::Selector.backends+ for the list of valid
975
+ # options. Note that the available options on your system will depend on the
976
+ # operating system. If you want to use the pure Ruby backend (not
977
+ # recommended due to its comparatively low performance), set environment
978
+ # variable +NIO4R_PURE+ to +true+.
979
+ #
980
+ # The default is +:auto+.
981
+ #
982
+ # @see https://github.com/socketry/nio4r/blob/master/lib/nio/selector.rb
983
+ #
984
+ def io_selector_backend(backend)
985
+ @options[:io_selector_backend] = backend.to_sym
986
+ end
987
+
988
+ def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
989
+ @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
990
+ end
991
+
992
+ private
993
+
994
+ # To avoid adding cert_pem and key_pem as URI params, we store them on the
995
+ # options[:store] from where Puma binder knows how to find and extract them.
996
+ def add_pem_values_to_options_store(opts)
997
+ return if defined?(JRUBY_VERSION)
998
+
999
+ @options[:store] ||= []
1000
+
1001
+ # Store cert_pem and key_pem to options[:store] if present
1002
+ [:cert, :key].each do |v|
1003
+ opt_key = :"#{v}_pem"
1004
+ if opts[opt_key]
1005
+ index = @options[:store].length
1006
+ @options[:store] << opts[opt_key]
1007
+ opts[v] = "store:#{index}"
1008
+ end
1009
+ end
1010
+ end
515
1011
  end
516
1012
  end