puma 3.12.1 → 5.6.4

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