puma 3.9.1 → 4.3.1
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.
- checksums.yaml +5 -5
- data/History.md +232 -0
- data/README.md +162 -224
- data/docs/architecture.md +37 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +24 -4
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/plugins.md +38 -0
- data/docs/restart.md +41 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +130 -37
- data/docs/tcp_mode.md +96 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -0
- data/ext/puma_http11/extconf.rb +13 -0
- data/ext/puma_http11/http11_parser.c +115 -140
- data/ext/puma_http11/http11_parser.java.rl +21 -37
- data/ext/puma_http11/http11_parser.rl +9 -9
- data/ext/puma_http11/http11_parser_common.rl +3 -3
- data/ext/puma_http11/mini_ssl.c +104 -8
- data/ext/puma_http11/org/jruby/puma/Http11.java +106 -114
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +90 -108
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +21 -4
- data/ext/puma_http11/puma_http11.c +2 -0
- data/lib/puma.rb +16 -0
- data/lib/puma/accept_nonblock.rb +7 -1
- data/lib/puma/app/status.rb +40 -26
- data/lib/puma/binder.rb +57 -74
- data/lib/puma/cli.rb +26 -7
- data/lib/puma/client.rb +243 -190
- data/lib/puma/cluster.rb +78 -34
- data/lib/puma/commonlogger.rb +2 -0
- data/lib/puma/configuration.rb +24 -16
- data/lib/puma/const.rb +36 -18
- data/lib/puma/control_cli.rb +46 -19
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +329 -68
- data/lib/puma/events.rb +6 -1
- data/lib/puma/io_buffer.rb +3 -6
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher.rb +120 -58
- data/lib/puma/minissl.rb +69 -27
- data/lib/puma/minissl/context_builder.rb +76 -0
- data/lib/puma/null_io.rb +2 -0
- data/lib/puma/plugin.rb +7 -2
- data/lib/puma/plugin/tmp_restart.rb +2 -1
- data/lib/puma/rack/builder.rb +4 -1
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +224 -34
- data/lib/puma/runner.rb +25 -4
- data/lib/puma/server.rb +148 -62
- data/lib/puma/single.rb +16 -5
- data/lib/puma/state_file.rb +2 -0
- data/lib/puma/tcp_logger.rb +2 -0
- data/lib/puma/thread_pool.rb +61 -38
- data/lib/puma/util.rb +2 -6
- data/lib/rack/handler/puma.rb +10 -4
- data/tools/docker/Dockerfile +16 -0
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +2 -0
- data/tools/jungle/init.d/puma +8 -8
- data/tools/jungle/init.d/run-puma +1 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/trickletest.rb +1 -2
- metadata +29 -56
- data/.github/issue_template.md +0 -20
- data/Gemfile +0 -14
- data/Manifest.txt +0 -78
- data/Rakefile +0 -165
- data/Release.md +0 -9
- data/gemfiles/2.1-Gemfile +0 -12
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/convenient.rb +0 -23
- data/lib/puma/daemon_ext.rb +0 -31
- data/lib/puma/delegation.rb +0 -11
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
- data/puma.gemspec +0 -20
data/lib/puma/control_cli.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'optparse'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
4
|
+
require_relative 'state_file'
|
5
|
+
require_relative 'const'
|
6
|
+
require_relative 'detect'
|
7
|
+
require_relative 'configuration'
|
6
8
|
require 'uri'
|
7
9
|
require 'socket'
|
8
10
|
|
9
11
|
module Puma
|
10
12
|
class ControlCLI
|
11
13
|
|
12
|
-
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory}
|
14
|
+
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats}
|
13
15
|
|
14
16
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
15
17
|
@state = nil
|
@@ -20,6 +22,7 @@ module Puma
|
|
20
22
|
@control_auth_token = nil
|
21
23
|
@config_file = nil
|
22
24
|
@command = nil
|
25
|
+
@environment = ENV['RACK_ENV']
|
23
26
|
|
24
27
|
@argv = argv.dup
|
25
28
|
@stdout = stdout
|
@@ -57,6 +60,11 @@ module Puma
|
|
57
60
|
@config_file = arg
|
58
61
|
end
|
59
62
|
|
63
|
+
o.on "-e", "--environment ENVIRONMENT",
|
64
|
+
"The environment to run the Rack app on (default development)" do |arg|
|
65
|
+
@environment = arg
|
66
|
+
end
|
67
|
+
|
60
68
|
o.on_tail("-H", "--help", "Show this message") do
|
61
69
|
@stdout.puts o
|
62
70
|
exit
|
@@ -69,12 +77,17 @@ module Puma
|
|
69
77
|
end
|
70
78
|
|
71
79
|
opts.order!(argv) { |a| opts.terminate a }
|
80
|
+
opts.parse!
|
72
81
|
|
73
82
|
@command = argv.shift
|
74
83
|
|
75
84
|
unless @config_file == '-'
|
76
|
-
|
77
|
-
|
85
|
+
environment = @environment || 'development'
|
86
|
+
|
87
|
+
if @config_file.nil?
|
88
|
+
@config_file = %W(config/puma/#{environment}.rb config/puma.rb).find do |f|
|
89
|
+
File.exist?(f)
|
90
|
+
end
|
78
91
|
end
|
79
92
|
|
80
93
|
if @config_file
|
@@ -98,7 +111,6 @@ module Puma
|
|
98
111
|
|
99
112
|
rescue => e
|
100
113
|
@stdout.puts e.message
|
101
|
-
@stdout.puts e.backtrace
|
102
114
|
exit 1
|
103
115
|
end
|
104
116
|
|
@@ -120,7 +132,7 @@ module Puma
|
|
120
132
|
@pid = sf.pid
|
121
133
|
elsif @pidfile
|
122
134
|
# get pid from pid_file
|
123
|
-
|
135
|
+
File.open(@pidfile) { |f| @pid = f.read.to_i }
|
124
136
|
end
|
125
137
|
end
|
126
138
|
|
@@ -128,7 +140,13 @@ module Puma
|
|
128
140
|
uri = URI.parse @control_url
|
129
141
|
|
130
142
|
# create server object by scheme
|
131
|
-
|
143
|
+
server = case uri.scheme
|
144
|
+
when "ssl"
|
145
|
+
require 'openssl'
|
146
|
+
OpenSSL::SSL::SSLSocket.new(
|
147
|
+
TCPSocket.new(uri.host, uri.port),
|
148
|
+
OpenSSL::SSL::SSLContext.new
|
149
|
+
).tap(&:connect)
|
132
150
|
when "tcp"
|
133
151
|
TCPSocket.new uri.host, uri.port
|
134
152
|
when "unix"
|
@@ -146,9 +164,9 @@ module Puma
|
|
146
164
|
url = url + "?token=#{@control_auth_token}"
|
147
165
|
end
|
148
166
|
|
149
|
-
|
167
|
+
server << "GET #{url} HTTP/1.0\r\n\r\n"
|
150
168
|
|
151
|
-
unless data =
|
169
|
+
unless data = server.read
|
152
170
|
raise "Server closed connection before responding"
|
153
171
|
end
|
154
172
|
|
@@ -169,10 +187,10 @@ module Puma
|
|
169
187
|
end
|
170
188
|
|
171
189
|
message "Command #{@command} sent success"
|
172
|
-
message response.last if @command == "stats"
|
190
|
+
message response.last if @command == "stats" || @command == "gc-stats"
|
173
191
|
end
|
174
|
-
|
175
|
-
|
192
|
+
ensure
|
193
|
+
server.close if server && !server.closed?
|
176
194
|
end
|
177
195
|
|
178
196
|
def send_signal
|
@@ -203,8 +221,17 @@ module Puma
|
|
203
221
|
when "phased-restart"
|
204
222
|
Process.kill "SIGUSR1", @pid
|
205
223
|
|
224
|
+
when "status"
|
225
|
+
begin
|
226
|
+
Process.kill 0, @pid
|
227
|
+
puts "Puma is started"
|
228
|
+
rescue Errno::ESRCH
|
229
|
+
raise "Puma is not running"
|
230
|
+
end
|
231
|
+
|
232
|
+
return
|
233
|
+
|
206
234
|
else
|
207
|
-
message "Puma is started"
|
208
235
|
return
|
209
236
|
end
|
210
237
|
|
@@ -220,7 +247,7 @@ module Puma
|
|
220
247
|
end
|
221
248
|
|
222
249
|
def run
|
223
|
-
start if @command == "start"
|
250
|
+
return start if @command == "start"
|
224
251
|
|
225
252
|
prepare_configuration
|
226
253
|
|
@@ -232,7 +259,6 @@ module Puma
|
|
232
259
|
|
233
260
|
rescue => e
|
234
261
|
message e.message
|
235
|
-
message e.backtrace
|
236
262
|
exit 1
|
237
263
|
end
|
238
264
|
|
@@ -245,9 +271,10 @@ module Puma
|
|
245
271
|
run_args += ["-S", @state] if @state
|
246
272
|
run_args += ["-q"] if @quiet
|
247
273
|
run_args += ["--pidfile", @pidfile] if @pidfile
|
248
|
-
run_args += ["--control", @control_url] if @control_url
|
274
|
+
run_args += ["--control-url", @control_url] if @control_url
|
249
275
|
run_args += ["--control-token", @control_auth_token] if @control_auth_token
|
250
276
|
run_args += ["-C", @config_file] if @config_file
|
277
|
+
run_args += ["-e", @environment] if @environment
|
251
278
|
|
252
279
|
events = Puma::Events.new @stdout, @stderr
|
253
280
|
|
data/lib/puma/detect.rb
CHANGED
data/lib/puma/dsl.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puma/const'
|
4
|
+
|
1
5
|
module Puma
|
2
|
-
# The methods that are available for use inside the
|
6
|
+
# The methods that are available for use inside the configuration file.
|
3
7
|
# These same methods are used in Puma cli and the rack handler
|
4
8
|
# internally.
|
5
9
|
#
|
@@ -24,7 +28,8 @@ module Puma
|
|
24
28
|
# puts config.options[:binds]
|
25
29
|
# # => "tcp://127.0.0.1:3002"
|
26
30
|
#
|
27
|
-
#
|
31
|
+
# You can also find many examples being used by the test suite in
|
32
|
+
# +test/config+.
|
28
33
|
class DSL
|
29
34
|
include ConfigDefault
|
30
35
|
|
@@ -55,6 +60,14 @@ module Puma
|
|
55
60
|
@plugins.clear
|
56
61
|
end
|
57
62
|
|
63
|
+
def set_default_host(host)
|
64
|
+
@options[:default_host] = host
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_host
|
68
|
+
@options[:default_host] || Configuration::DefaultTCPHost
|
69
|
+
end
|
70
|
+
|
58
71
|
def inject(&blk)
|
59
72
|
instance_eval(&blk)
|
60
73
|
end
|
@@ -69,9 +82,22 @@ module Puma
|
|
69
82
|
@plugins << @config.load_plugin(name)
|
70
83
|
end
|
71
84
|
|
72
|
-
# Use
|
73
|
-
# be the
|
85
|
+
# Use an object or block as the rack application. This allows the
|
86
|
+
# configuration file to be the application itself.
|
74
87
|
#
|
88
|
+
# @example
|
89
|
+
# app do |env|
|
90
|
+
# body = 'Hello, World!'
|
91
|
+
#
|
92
|
+
# [
|
93
|
+
# 200,
|
94
|
+
# {
|
95
|
+
# 'Content-Type' => 'text/plain',
|
96
|
+
# 'Content-Length' => body.length.to_s
|
97
|
+
# },
|
98
|
+
# [body]
|
99
|
+
# ]
|
100
|
+
# end
|
75
101
|
def app(obj=nil, &block)
|
76
102
|
obj ||= block
|
77
103
|
|
@@ -80,9 +106,20 @@ module Puma
|
|
80
106
|
@options[:app] = obj
|
81
107
|
end
|
82
108
|
|
83
|
-
# Start the Puma control rack
|
84
|
-
# with to control the main server.
|
109
|
+
# Start the Puma control rack application on +url+. This application can
|
110
|
+
# be communicated with to control the main server. Additionally, you can
|
111
|
+
# provide an authentication token, so all requests to the control server
|
112
|
+
# will need to include that token as a query parameter. This allows for
|
113
|
+
# simple authentication.
|
114
|
+
#
|
115
|
+
# Check out {Puma::App::Status} to see what the app has available.
|
85
116
|
#
|
117
|
+
# @example
|
118
|
+
# activate_control_app 'unix:///var/run/pumactl.sock'
|
119
|
+
# @example
|
120
|
+
# activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
|
121
|
+
# @example
|
122
|
+
# activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
|
86
123
|
def activate_control_app(url="auto", opts={})
|
87
124
|
if url == "auto"
|
88
125
|
path = Configuration.temp_path
|
@@ -93,7 +130,12 @@ module Puma
|
|
93
130
|
end
|
94
131
|
|
95
132
|
if opts[:no_token]
|
96
|
-
|
133
|
+
# We need to use 'none' rather than :none because this value will be
|
134
|
+
# passed on to an instance of OptionParser, which doesn't support
|
135
|
+
# symbols as option values.
|
136
|
+
#
|
137
|
+
# See: https://github.com/puma/puma/issues/1193#issuecomment-305995488
|
138
|
+
auth_token = 'none'
|
97
139
|
else
|
98
140
|
auth_token = opts[:auth_token]
|
99
141
|
auth_token ||= Configuration.random_token
|
@@ -110,50 +152,93 @@ module Puma
|
|
110
152
|
@options[:config_files] << file
|
111
153
|
end
|
112
154
|
|
113
|
-
# Bind the server to +url+. tcp:// and
|
114
|
-
# protocols.
|
155
|
+
# Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
|
156
|
+
# accepted protocols. Multiple urls can be bound to, calling `bind` does
|
157
|
+
# not overwrite previous bindings.
|
115
158
|
#
|
159
|
+
# The default is "tcp://0.0.0.0:9292".
|
160
|
+
#
|
161
|
+
# You can use query parameters within the url to specify options:
|
162
|
+
#
|
163
|
+
# - Set the socket backlog depth with +backlog+, default is 1024.
|
164
|
+
# - Set up an SSL certificate with +key+ & +cert+.
|
165
|
+
# - Set whether to optimize for low latency instead of throughput with
|
166
|
+
# +low_latency+, default is to optimize for low latency. This is done
|
167
|
+
# via +Socket::TCP_NODELAY+.
|
168
|
+
# - Set socket permissions with +umask+.
|
169
|
+
#
|
170
|
+
# @example Backlog depth
|
171
|
+
# bind 'unix:///var/run/puma.sock?backlog=512'
|
172
|
+
# @example SSL cert
|
173
|
+
# bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
|
174
|
+
# @example Disable optimization for low latency
|
175
|
+
# bind 'tcp://0.0.0.0:9292?low_latency=false'
|
176
|
+
# @example Socket permissions
|
177
|
+
# bind 'unix:///var/run/puma.sock?umask=0111'
|
116
178
|
def bind(url)
|
117
179
|
@options[:binds] ||= []
|
118
180
|
@options[:binds] << url
|
119
181
|
end
|
120
182
|
|
183
|
+
def clear_binds!
|
184
|
+
@options[:binds] = []
|
185
|
+
end
|
186
|
+
|
121
187
|
# Define the TCP port to bind to. Use +bind+ for more advanced options.
|
122
188
|
#
|
189
|
+
# @example
|
190
|
+
# port 9292
|
123
191
|
def port(port, host=nil)
|
124
|
-
host ||=
|
192
|
+
host ||= default_host
|
125
193
|
bind "tcp://#{host}:#{port}"
|
126
194
|
end
|
127
195
|
|
128
|
-
# Define how long persistent connections can be idle before
|
129
|
-
# them
|
130
|
-
#
|
196
|
+
# Define how long persistent connections can be idle before Puma closes
|
197
|
+
# them.
|
131
198
|
def persistent_timeout(seconds)
|
132
|
-
@options[:persistent_timeout] = seconds
|
199
|
+
@options[:persistent_timeout] = Integer(seconds)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Define how long the tcp socket stays open, if no data has been received.
|
203
|
+
def first_data_timeout(seconds)
|
204
|
+
@options[:first_data_timeout] = Integer(seconds)
|
133
205
|
end
|
134
206
|
|
135
207
|
# Work around leaky apps that leave garbage in Thread locals
|
136
|
-
# across requests
|
137
|
-
#
|
208
|
+
# across requests.
|
138
209
|
def clean_thread_locals(which=true)
|
139
210
|
@options[:clean_thread_locals] = which
|
140
211
|
end
|
141
212
|
|
142
|
-
# Daemonize the server into the background.
|
143
|
-
# this
|
213
|
+
# Daemonize the server into the background. It's highly recommended to
|
214
|
+
# use this in combination with +pidfile+ and +stdout_redirect+.
|
215
|
+
#
|
216
|
+
# The default is "false".
|
217
|
+
#
|
218
|
+
# @example
|
219
|
+
# daemonize
|
220
|
+
#
|
221
|
+
# @example
|
222
|
+
# daemonize false
|
144
223
|
def daemonize(which=true)
|
145
224
|
@options[:daemon] = which
|
146
225
|
end
|
147
226
|
|
148
227
|
# When shutting down, drain the accept socket of pending
|
149
|
-
# connections and
|
228
|
+
# connections and process them. This loops over the accept
|
150
229
|
# socket until there are no more read events and then stops
|
151
230
|
# looking and waits for the requests to finish.
|
152
231
|
def drain_on_shutdown(which=true)
|
153
232
|
@options[:drain_on_shutdown] = which
|
154
233
|
end
|
155
234
|
|
156
|
-
# Set the environment in which the
|
235
|
+
# Set the environment in which the rack's app will run. The value must be
|
236
|
+
# a string.
|
237
|
+
#
|
238
|
+
# The default is "development".
|
239
|
+
#
|
240
|
+
# @example
|
241
|
+
# environment 'production'
|
157
242
|
def environment(environment)
|
158
243
|
@options[:environment] = environment
|
159
244
|
end
|
@@ -179,30 +264,41 @@ module Puma
|
|
179
264
|
end
|
180
265
|
|
181
266
|
# Code to run before doing a restart. This code should
|
182
|
-
# close
|
267
|
+
# close log files, database connections, etc.
|
183
268
|
#
|
184
269
|
# This can be called multiple times to add code each time.
|
185
270
|
#
|
271
|
+
# @example
|
272
|
+
# on_restart do
|
273
|
+
# puts 'On restart...'
|
274
|
+
# end
|
186
275
|
def on_restart(&block)
|
187
276
|
@options[:on_restart] ||= []
|
188
277
|
@options[:on_restart] << block
|
189
278
|
end
|
190
279
|
|
191
|
-
# Command to use to restart
|
192
|
-
# load
|
193
|
-
# to
|
280
|
+
# Command to use to restart Puma. This should be just how to
|
281
|
+
# load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
|
282
|
+
# to Puma, as those are the same as the original process.
|
194
283
|
#
|
284
|
+
# @example
|
285
|
+
# restart_command '/u/app/lolcat/bin/restart_puma'
|
195
286
|
def restart_command(cmd)
|
196
287
|
@options[:restart_cmd] = cmd.to_s
|
197
288
|
end
|
198
289
|
|
199
|
-
# Store the pid of the server in the file at
|
290
|
+
# Store the pid of the server in the file at "path".
|
291
|
+
#
|
292
|
+
# @example
|
293
|
+
# pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
|
200
294
|
def pidfile(path)
|
201
295
|
@options[:pidfile] = path.to_s
|
202
296
|
end
|
203
297
|
|
204
|
-
# Disable request logging.
|
298
|
+
# Disable request logging, if this isn't used it'll be enabled by default.
|
205
299
|
#
|
300
|
+
# @example
|
301
|
+
# quiet
|
206
302
|
def quiet(which=true)
|
207
303
|
@options[:log_requests] = !which
|
208
304
|
end
|
@@ -221,6 +317,10 @@ module Puma
|
|
221
317
|
|
222
318
|
# Load +path+ as a rackup file.
|
223
319
|
#
|
320
|
+
# The default is "config.ru".
|
321
|
+
#
|
322
|
+
# @example
|
323
|
+
# rackup '/u/apps/lolcat/config.ru'
|
224
324
|
def rackup(path)
|
225
325
|
@options[:rackup] = path.to_s
|
226
326
|
end
|
@@ -231,16 +331,36 @@ module Puma
|
|
231
331
|
@options[:mode] = :tcp
|
232
332
|
end
|
233
333
|
|
234
|
-
|
334
|
+
def early_hints(answer=true)
|
335
|
+
@options[:early_hints] = answer
|
336
|
+
end
|
337
|
+
|
338
|
+
# Redirect STDOUT and STDERR to files specified. The +append+ parameter
|
339
|
+
# specifies whether the output is appended, the default is +false+.
|
340
|
+
#
|
341
|
+
# @example
|
342
|
+
# stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
|
343
|
+
# @example
|
344
|
+
# stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
|
235
345
|
def stdout_redirect(stdout=nil, stderr=nil, append=false)
|
236
346
|
@options[:redirect_stdout] = stdout
|
237
347
|
@options[:redirect_stderr] = stderr
|
238
348
|
@options[:redirect_append] = append
|
239
349
|
end
|
240
350
|
|
351
|
+
def log_formatter(&block)
|
352
|
+
@options[:log_formatter] = block
|
353
|
+
end
|
354
|
+
|
241
355
|
# Configure +min+ to be the minimum number of threads to use to answer
|
242
356
|
# requests and +max+ the maximum.
|
243
357
|
#
|
358
|
+
# The default is "0, 16".
|
359
|
+
#
|
360
|
+
# @example
|
361
|
+
# threads 0, 16
|
362
|
+
# @example
|
363
|
+
# threads 5, 5
|
244
364
|
def threads(min, max)
|
245
365
|
min = Integer(min)
|
246
366
|
max = Integer(max)
|
@@ -256,81 +376,135 @@ module Puma
|
|
256
376
|
@options[:max_threads] = max
|
257
377
|
end
|
258
378
|
|
379
|
+
# Instead of "bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'" you
|
380
|
+
# can also use the "ssl_bind" option.
|
381
|
+
#
|
382
|
+
# @example
|
383
|
+
# ssl_bind '127.0.0.1', '9292', {
|
384
|
+
# cert: path_to_cert,
|
385
|
+
# key: path_to_key,
|
386
|
+
# ssl_cipher_filter: cipher_filter, # optional
|
387
|
+
# verify_mode: verify_mode, # default 'none'
|
388
|
+
# }
|
389
|
+
# @example For JRuby additional keys are required: keystore & keystore_pass.
|
390
|
+
# ssl_bind '127.0.0.1', '9292', {
|
391
|
+
# cert: path_to_cert,
|
392
|
+
# key: path_to_key,
|
393
|
+
# ssl_cipher_filter: cipher_filter, # optional
|
394
|
+
# verify_mode: verify_mode, # default 'none'
|
395
|
+
# keystore: path_to_keystore,
|
396
|
+
# keystore_pass: password
|
397
|
+
# }
|
259
398
|
def ssl_bind(host, port, opts)
|
260
|
-
verify = opts.fetch(:verify_mode, 'none')
|
399
|
+
verify = opts.fetch(:verify_mode, 'none').to_s
|
400
|
+
no_tlsv1 = opts.fetch(:no_tlsv1, 'false')
|
401
|
+
no_tlsv1_1 = opts.fetch(:no_tlsv1_1, 'false')
|
402
|
+
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
261
403
|
|
262
404
|
if defined?(JRUBY_VERSION)
|
263
405
|
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
264
|
-
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}"
|
406
|
+
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
|
265
407
|
else
|
266
|
-
|
408
|
+
ssl_cipher_filter = "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" if opts[:ssl_cipher_filter]
|
409
|
+
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}#{ssl_cipher_filter}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
|
267
410
|
end
|
268
411
|
end
|
269
412
|
|
270
413
|
# Use +path+ as the file to store the server info state. This is
|
271
|
-
# used by pumactl to query and control the server.
|
414
|
+
# used by +pumactl+ to query and control the server.
|
272
415
|
#
|
416
|
+
# @example
|
417
|
+
# state_path '/u/apps/lolcat/tmp/pids/puma.state'
|
273
418
|
def state_path(path)
|
274
419
|
@options[:state] = path.to_s
|
275
420
|
end
|
276
421
|
|
277
|
-
#
|
422
|
+
# How many worker processes to run. Typically this is set to
|
423
|
+
# to the number of available cores.
|
424
|
+
#
|
425
|
+
# The default is 0.
|
278
426
|
#
|
427
|
+
# @note Cluster mode only.
|
279
428
|
def workers(count)
|
280
429
|
@options[:workers] = count.to_i
|
281
430
|
end
|
282
431
|
|
283
|
-
#
|
432
|
+
# Code to run immediately before master process
|
284
433
|
# forks workers (once on boot). These hooks can block if necessary
|
285
|
-
# to wait for background operations unknown to
|
434
|
+
# to wait for background operations unknown to Puma to finish before
|
286
435
|
# the process terminates.
|
287
|
-
# This can be used to close any connections to remote servers (database,
|
288
|
-
# that were opened when preloading the code
|
436
|
+
# This can be used to close any connections to remote servers (database,
|
437
|
+
# Redis, ...) that were opened when preloading the code.
|
289
438
|
#
|
290
|
-
# This can be called multiple times to add hooks.
|
439
|
+
# This can be called multiple times to add several hooks.
|
291
440
|
#
|
441
|
+
# @note Cluster mode only.
|
442
|
+
# @example
|
443
|
+
# before_fork do
|
444
|
+
# puts "Starting workers..."
|
445
|
+
# end
|
292
446
|
def before_fork(&block)
|
293
447
|
@options[:before_fork] ||= []
|
294
448
|
@options[:before_fork] << block
|
295
449
|
end
|
296
450
|
|
297
|
-
#
|
451
|
+
# Code to run in a worker when it boots to setup
|
298
452
|
# the process before booting the app.
|
299
453
|
#
|
300
|
-
# This can be called multiple times to add hooks.
|
454
|
+
# This can be called multiple times to add several hooks.
|
301
455
|
#
|
456
|
+
# @note Cluster mode only.
|
457
|
+
# @example
|
458
|
+
# on_worker_fork do
|
459
|
+
# puts 'Before worker fork...'
|
460
|
+
# end
|
302
461
|
def on_worker_boot(&block)
|
303
462
|
@options[:before_worker_boot] ||= []
|
304
463
|
@options[:before_worker_boot] << block
|
305
464
|
end
|
306
465
|
|
307
|
-
#
|
466
|
+
# Code to run immediately before a worker shuts
|
308
467
|
# down (after it has finished processing HTTP requests). These hooks
|
309
468
|
# can block if necessary to wait for background operations unknown
|
310
|
-
# to
|
469
|
+
# to Puma to finish before the process terminates.
|
311
470
|
#
|
312
|
-
# This can be called multiple times to add hooks.
|
471
|
+
# This can be called multiple times to add several hooks.
|
313
472
|
#
|
473
|
+
# @note Cluster mode only.
|
474
|
+
# @example
|
475
|
+
# on_worker_shutdown do
|
476
|
+
# puts 'On worker shutdown...'
|
477
|
+
# end
|
314
478
|
def on_worker_shutdown(&block)
|
315
479
|
@options[:before_worker_shutdown] ||= []
|
316
480
|
@options[:before_worker_shutdown] << block
|
317
481
|
end
|
318
482
|
|
319
|
-
#
|
320
|
-
#
|
483
|
+
# Code to run in the master right before a worker is started. The worker's
|
484
|
+
# index is passed as an argument.
|
321
485
|
#
|
322
|
-
# This can be called multiple times to add hooks.
|
486
|
+
# This can be called multiple times to add several hooks.
|
323
487
|
#
|
488
|
+
# @note Cluster mode only.
|
489
|
+
# @example
|
490
|
+
# on_worker_fork do
|
491
|
+
# puts 'Before worker fork...'
|
492
|
+
# end
|
324
493
|
def on_worker_fork(&block)
|
325
494
|
@options[:before_worker_fork] ||= []
|
326
495
|
@options[:before_worker_fork] << block
|
327
496
|
end
|
328
497
|
|
329
|
-
#
|
330
|
-
#
|
498
|
+
# Code to run in the master after a worker has been started. The worker's
|
499
|
+
# index is passed as an argument.
|
331
500
|
#
|
332
|
-
# This
|
501
|
+
# This is called everytime a worker is to be started.
|
333
502
|
#
|
503
|
+
# @note Cluster mode only.
|
504
|
+
# @example
|
505
|
+
# after_worker_fork do
|
506
|
+
# puts 'After worker fork...'
|
507
|
+
# end
|
334
508
|
def after_worker_fork(&block)
|
335
509
|
@options[:after_worker_fork] ||= []
|
336
510
|
@options[:after_worker_fork] = block
|
@@ -338,7 +512,26 @@ module Puma
|
|
338
512
|
|
339
513
|
alias_method :after_worker_boot, :after_worker_fork
|
340
514
|
|
515
|
+
# Code to run out-of-band when the worker is idle.
|
516
|
+
# These hooks run immediately after a request has finished
|
517
|
+
# processing and there are no busy threads on the worker.
|
518
|
+
# The worker doesn't accept new requests until this code finishes.
|
519
|
+
#
|
520
|
+
# This hook is useful for running out-of-band garbage collection
|
521
|
+
# or scheduling asynchronous tasks to execute after a response.
|
522
|
+
#
|
523
|
+
# This can be called multiple times to add several hooks.
|
524
|
+
def out_of_band(&block)
|
525
|
+
@options[:out_of_band] ||= []
|
526
|
+
@options[:out_of_band] << block
|
527
|
+
end
|
528
|
+
|
341
529
|
# The directory to operate out of.
|
530
|
+
#
|
531
|
+
# The default is the current directory.
|
532
|
+
#
|
533
|
+
# @example
|
534
|
+
# directory '/u/apps/lolcat'
|
342
535
|
def directory(dir)
|
343
536
|
@options[:directory] = dir.to_s
|
344
537
|
end
|
@@ -349,22 +542,28 @@ module Puma
|
|
349
542
|
directory dir
|
350
543
|
end
|
351
544
|
|
352
|
-
# Run the app as a raw TCP app instead of an HTTP rack app
|
545
|
+
# Run the app as a raw TCP app instead of an HTTP rack app.
|
353
546
|
def tcp_mode
|
354
547
|
@options[:mode] = :tcp
|
355
548
|
end
|
356
549
|
|
357
|
-
#
|
358
|
-
#
|
359
|
-
# with using the phased restart feature, you can't use both.
|
550
|
+
# Preload the application before starting the workers; this conflicts with
|
551
|
+
# phased restart feature. This is off by default.
|
360
552
|
#
|
553
|
+
# @note Cluster mode only.
|
554
|
+
# @example
|
555
|
+
# preload_app!
|
361
556
|
def preload_app!(answer=true)
|
362
557
|
@options[:preload_app] = answer
|
363
558
|
end
|
364
559
|
|
365
|
-
# Use +obj+ or +block+ as the low level error handler. This allows
|
366
|
-
# change the default error on the server.
|
560
|
+
# Use +obj+ or +block+ as the low level error handler. This allows the
|
561
|
+
# configuration file to change the default error on the server.
|
367
562
|
#
|
563
|
+
# @example
|
564
|
+
# lowlevel_error_handler do |err|
|
565
|
+
# [200, {}, ["error page"]]
|
566
|
+
# end
|
368
567
|
def lowlevel_error_handler(obj=nil, &block)
|
369
568
|
obj ||= block
|
370
569
|
raise "Provide either a #call'able or a block" unless obj
|
@@ -374,40 +573,102 @@ module Puma
|
|
374
573
|
# This option is used to allow your app and its gems to be
|
375
574
|
# properly reloaded when not using preload.
|
376
575
|
#
|
377
|
-
# When set, if
|
576
|
+
# When set, if Puma detects that it's been invoked in the
|
378
577
|
# context of Bundler, it will cleanup the environment and
|
379
578
|
# re-run itself outside the Bundler environment, but directly
|
380
579
|
# using the files that Bundler has setup.
|
381
580
|
#
|
382
|
-
# This means that
|
581
|
+
# This means that Puma is now decoupled from your Bundler
|
383
582
|
# context and when each worker loads, it will be loading a
|
384
583
|
# new Bundler context and thus can float around as the release
|
385
584
|
# dictates.
|
585
|
+
#
|
586
|
+
# See also: extra_runtime_dependencies
|
587
|
+
#
|
588
|
+
# @note This is incompatible with +preload_app!+.
|
589
|
+
# @note This is only supported for RubyGems 2.2+
|
386
590
|
def prune_bundler(answer=true)
|
387
591
|
@options[:prune_bundler] = answer
|
388
592
|
end
|
389
593
|
|
390
|
-
#
|
594
|
+
# By default, Puma will raise SignalException when SIGTERM is received. In
|
595
|
+
# environments where SIGTERM is something expected, you can suppress these
|
596
|
+
# with this option.
|
597
|
+
#
|
598
|
+
# This can be useful for example in Kubernetes, where rolling restart is
|
599
|
+
# guaranteed usually on infrastructure level.
|
600
|
+
#
|
601
|
+
# @example
|
602
|
+
# raise_exception_on_sigterm false
|
603
|
+
def raise_exception_on_sigterm(answer=true)
|
604
|
+
@options[:raise_exception_on_sigterm] = answer
|
605
|
+
end
|
606
|
+
|
607
|
+
# When using prune_bundler, if extra runtime dependencies need to be loaded to
|
608
|
+
# initialize your app, then this setting can be used. This includes any Puma plugins.
|
609
|
+
#
|
610
|
+
# Before bundler is pruned, the gem names supplied will be looked up in the bundler
|
611
|
+
# context and then loaded again after bundler is pruned.
|
612
|
+
# Only applies if prune_bundler is used.
|
613
|
+
#
|
614
|
+
# @example
|
615
|
+
# extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
|
616
|
+
# @example
|
617
|
+
# extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
|
618
|
+
def extra_runtime_dependencies(answer = [])
|
619
|
+
@options[:extra_runtime_dependencies] = Array(answer)
|
620
|
+
end
|
621
|
+
|
622
|
+
# Additional text to display in process listing.
|
623
|
+
#
|
624
|
+
# If you do not specify a tag, Puma will infer it. If you do not want Puma
|
625
|
+
# to add a tag, use an empty string.
|
626
|
+
#
|
627
|
+
# @example
|
628
|
+
# tag 'app name'
|
629
|
+
# @example
|
630
|
+
# tag ''
|
391
631
|
def tag(string)
|
392
632
|
@options[:tag] = string.to_s
|
393
633
|
end
|
394
634
|
|
395
|
-
#
|
396
|
-
#
|
397
|
-
#
|
398
|
-
#
|
635
|
+
# Verifies that all workers have checked in to the master process within
|
636
|
+
# the given timeout. If not the worker process will be restarted. This is
|
637
|
+
# not a request timeout, it is to protect against a hung or dead process.
|
638
|
+
# Setting this value will not protect against slow requests.
|
639
|
+
#
|
640
|
+
# The minimum value is 6 seconds, the default value is 60 seconds.
|
641
|
+
#
|
642
|
+
# @note Cluster mode only.
|
643
|
+
# @example
|
644
|
+
# worker_timeout 60
|
399
645
|
def worker_timeout(timeout)
|
646
|
+
timeout = Integer(timeout)
|
647
|
+
min = Const::WORKER_CHECK_INTERVAL
|
648
|
+
|
649
|
+
if timeout <= min
|
650
|
+
raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
|
651
|
+
end
|
652
|
+
|
400
653
|
@options[:worker_timeout] = timeout
|
401
654
|
end
|
402
655
|
|
403
|
-
#
|
656
|
+
# Change the default worker timeout for booting.
|
657
|
+
#
|
658
|
+
# If unspecified, this defaults to the value of worker_timeout.
|
659
|
+
#
|
660
|
+
# @note Cluster mode only.
|
661
|
+
# @example:
|
662
|
+
# worker_boot_timeout 60
|
404
663
|
def worker_boot_timeout(timeout)
|
405
|
-
@options[:worker_boot_timeout] = timeout
|
664
|
+
@options[:worker_boot_timeout] = Integer(timeout)
|
406
665
|
end
|
407
666
|
|
408
|
-
#
|
667
|
+
# Set the timeout for worker shutdown
|
668
|
+
#
|
669
|
+
# @note Cluster mode only.
|
409
670
|
def worker_shutdown_timeout(timeout)
|
410
|
-
@options[:worker_shutdown_timeout] = timeout
|
671
|
+
@options[:worker_shutdown_timeout] = Integer(timeout)
|
411
672
|
end
|
412
673
|
|
413
674
|
# When set to true (the default), workers accept all requests
|
@@ -422,7 +683,7 @@ module Puma
|
|
422
683
|
# Note that setting this to false disables HTTP keepalive and
|
423
684
|
# slow clients will occupy a handler thread while the request
|
424
685
|
# is being sent. A reverse proxy, such as nginx, can handle
|
425
|
-
# slow clients and queue requests before they reach
|
686
|
+
# slow clients and queue requests before they reach Puma.
|
426
687
|
def queue_requests(answer=true)
|
427
688
|
@options[:queue_requests] = answer
|
428
689
|
end
|
@@ -451,7 +712,7 @@ module Puma
|
|
451
712
|
# is used, allowing headers such as X-Forwarded-For
|
452
713
|
# to be used as well.
|
453
714
|
# * Any string - this allows you to hardcode remote address to any value
|
454
|
-
# you wish. Because
|
715
|
+
# you wish. Because Puma never uses this field anyway, it's
|
455
716
|
# format is entirely in your hands.
|
456
717
|
def set_remote_address(val=:socket)
|
457
718
|
case val
|
@@ -466,7 +727,7 @@ module Puma
|
|
466
727
|
when Hash
|
467
728
|
if hdr = val[:header]
|
468
729
|
@options[:remote_address] = :header
|
469
|
-
@options[:remote_address_header] = "HTTP_" + hdr.upcase.
|
730
|
+
@options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
|
470
731
|
else
|
471
732
|
raise "Invalid value for set_remote_address - #{val.inspect}"
|
472
733
|
end
|