puma 3.4.0 → 3.12.0
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.txt → History.md} +356 -74
- data/README.md +143 -227
- data/docs/architecture.md +36 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +1 -1
- 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 +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +124 -22
- data/ext/puma_http11/extconf.rb +2 -0
- data/ext/puma_http11/http11_parser.c +291 -447
- data/ext/puma_http11/http11_parser.h +1 -0
- data/ext/puma_http11/http11_parser.rl +10 -9
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/io_buffer.c +7 -7
- data/ext/puma_http11/mini_ssl.c +67 -6
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +76 -94
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +15 -2
- data/ext/puma_http11/puma_http11.c +1 -0
- data/lib/puma.rb +13 -5
- data/lib/puma/app/status.rb +8 -0
- data/lib/puma/binder.rb +46 -21
- data/lib/puma/cli.rb +49 -33
- data/lib/puma/client.rb +149 -4
- data/lib/puma/cluster.rb +55 -13
- data/lib/puma/commonlogger.rb +19 -20
- data/lib/puma/compat.rb +3 -7
- data/lib/puma/configuration.rb +136 -131
- data/lib/puma/const.rb +19 -37
- data/lib/puma/control_cli.rb +38 -35
- data/lib/puma/convenient.rb +3 -3
- data/lib/puma/detect.rb +3 -1
- data/lib/puma/dsl.rb +86 -57
- data/lib/puma/events.rb +17 -13
- data/lib/puma/io_buffer.rb +1 -1
- data/lib/puma/jruby_restart.rb +0 -1
- data/lib/puma/launcher.rb +61 -30
- data/lib/puma/minissl.rb +85 -4
- data/lib/puma/null_io.rb +6 -13
- data/lib/puma/plugin.rb +12 -1
- data/lib/puma/plugin/tmp_restart.rb +1 -2
- data/lib/puma/rack/builder.rb +3 -0
- data/lib/puma/rack/urlmap.rb +9 -8
- data/lib/puma/reactor.rb +144 -0
- data/lib/puma/runner.rb +27 -1
- data/lib/puma/server.rb +135 -33
- data/lib/puma/single.rb +17 -3
- data/lib/puma/tcp_logger.rb +8 -1
- data/lib/puma/thread_pool.rb +70 -20
- data/lib/puma/util.rb +1 -5
- data/lib/rack/handler/puma.rb +58 -17
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +9 -2
- data/tools/jungle/init.d/puma +85 -58
- data/tools/jungle/init.d/run-puma +16 -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/jungle/upstart/puma.conf +1 -1
- data/tools/trickletest.rb +1 -1
- metadata +22 -94
- data/Gemfile +0 -13
- data/Manifest.txt +0 -78
- data/Rakefile +0 -158
- data/docs/config.md +0 -0
- data/lib/puma/rack/backports/uri/common_18.rb +0 -59
- data/lib/puma/rack/backports/uri/common_192.rb +0 -55
- data/puma.gemspec +0 -52
data/lib/puma/const.rb
CHANGED
@@ -53,6 +53,8 @@ module Puma
|
|
53
53
|
415 => 'Unsupported Media Type',
|
54
54
|
416 => 'Range Not Satisfiable',
|
55
55
|
417 => 'Expectation Failed',
|
56
|
+
418 => 'I\'m A Teapot',
|
57
|
+
421 => 'Misdirected Request',
|
56
58
|
422 => 'Unprocessable Entity',
|
57
59
|
423 => 'Locked',
|
58
60
|
424 => 'Failed Dependency',
|
@@ -60,6 +62,7 @@ module Puma
|
|
60
62
|
428 => 'Precondition Required',
|
61
63
|
429 => 'Too Many Requests',
|
62
64
|
431 => 'Request Header Fields Too Large',
|
65
|
+
451 => 'Unavailable For Legal Reasons',
|
63
66
|
500 => 'Internal Server Error',
|
64
67
|
501 => 'Not Implemented',
|
65
68
|
502 => 'Bad Gateway',
|
@@ -73,19 +76,14 @@ module Puma
|
|
73
76
|
511 => 'Network Authentication Required'
|
74
77
|
}
|
75
78
|
|
76
|
-
SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message|
|
77
|
-
[message.downcase.gsub(/\s|-|'/, '_').to_sym, code]
|
78
|
-
}.flatten]
|
79
|
-
|
80
79
|
# For some HTTP status codes the client only expects headers.
|
81
80
|
#
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
STATUS_WITH_NO_ENTITY_BODY = no_body
|
82
|
+
STATUS_WITH_NO_ENTITY_BODY = {
|
83
|
+
204 => true,
|
84
|
+
205 => true,
|
85
|
+
304 => true
|
86
|
+
}
|
89
87
|
|
90
88
|
# Frequently used constants when constructing requests or responses. Many times
|
91
89
|
# the constant just refers to a string with the same contents. Using these constants
|
@@ -100,10 +98,10 @@ module Puma
|
|
100
98
|
# too taxing on performance.
|
101
99
|
module Const
|
102
100
|
|
103
|
-
PUMA_VERSION = VERSION = "3.
|
104
|
-
CODE_NAME = "
|
101
|
+
PUMA_VERSION = VERSION = "3.12.0".freeze
|
102
|
+
CODE_NAME = "Llamas in Pajamas".freeze
|
105
103
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
106
|
-
|
104
|
+
|
107
105
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
108
106
|
|
109
107
|
# The default number of seconds for another request within a persistent
|
@@ -118,15 +116,6 @@ module Puma
|
|
118
116
|
# sending data back
|
119
117
|
WRITE_TIMEOUT = 10
|
120
118
|
|
121
|
-
# How long, after raising the ForceShutdown of a thread during
|
122
|
-
# forced shutdown mode, to wait for the thread to try and finish
|
123
|
-
# up it's work before leaving the thread to die on the vine.
|
124
|
-
SHUTDOWN_GRACE_TIME = 5 # seconds
|
125
|
-
|
126
|
-
DATE = "Date".freeze
|
127
|
-
|
128
|
-
SCRIPT_NAME = "SCRIPT_NAME".freeze
|
129
|
-
|
130
119
|
# The original URI requested by the client.
|
131
120
|
REQUEST_URI= 'REQUEST_URI'.freeze
|
132
121
|
REQUEST_PATH = 'REQUEST_PATH'.freeze
|
@@ -163,26 +152,12 @@ module Puma
|
|
163
152
|
# Maximum request body size before it is moved out of memory and into a tempfile for reading.
|
164
153
|
MAX_BODY = MAX_HEADER
|
165
154
|
|
166
|
-
# A frozen format for this is about 15% faster
|
167
|
-
STATUS_FORMAT = "HTTP/1.1 %d %s\r\nConnection: close\r\n".freeze
|
168
|
-
|
169
|
-
CONTENT_TYPE = "Content-Type".freeze
|
170
|
-
|
171
|
-
LAST_MODIFIED = "Last-Modified".freeze
|
172
|
-
ETAG = "ETag".freeze
|
173
|
-
SLASH = "/".freeze
|
174
155
|
REQUEST_METHOD = "REQUEST_METHOD".freeze
|
175
|
-
GET = "GET".freeze
|
176
156
|
HEAD = "HEAD".freeze
|
177
157
|
# ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
|
178
|
-
ETAG_FORMAT = "\"%x-%x-%x\"".freeze
|
179
158
|
LINE_END = "\r\n".freeze
|
180
159
|
REMOTE_ADDR = "REMOTE_ADDR".freeze
|
181
160
|
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
|
182
|
-
HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
|
183
|
-
HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
|
184
|
-
REDIRECT = "HTTP/1.1 302 Found\r\nLocation: %s\r\nConnection: close\r\n\r\n".freeze
|
185
|
-
HOST = "HOST".freeze
|
186
161
|
|
187
162
|
SERVER_NAME = "SERVER_NAME".freeze
|
188
163
|
SERVER_PORT = "SERVER_PORT".freeze
|
@@ -195,7 +170,6 @@ module Puma
|
|
195
170
|
|
196
171
|
SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
|
197
172
|
HTTP_11 = "HTTP/1.1".freeze
|
198
|
-
HTTP_10 = "HTTP/1.0".freeze
|
199
173
|
|
200
174
|
SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
|
201
175
|
GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
|
@@ -219,7 +193,10 @@ module Puma
|
|
219
193
|
|
220
194
|
HTTP_VERSION = "HTTP_VERSION".freeze
|
221
195
|
HTTP_CONNECTION = "HTTP_CONNECTION".freeze
|
196
|
+
HTTP_EXPECT = "HTTP_EXPECT".freeze
|
197
|
+
CONTINUE = "100-continue".freeze
|
222
198
|
|
199
|
+
HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n".freeze
|
223
200
|
HTTP_11_200 = "HTTP/1.1 200 OK\r\n".freeze
|
224
201
|
HTTP_10_200 = "HTTP/1.0 200 OK\r\n".freeze
|
225
202
|
|
@@ -229,6 +206,7 @@ module Puma
|
|
229
206
|
CONTENT_LENGTH2 = "content-length".freeze
|
230
207
|
CONTENT_LENGTH_S = "Content-Length: ".freeze
|
231
208
|
TRANSFER_ENCODING = "transfer-encoding".freeze
|
209
|
+
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING".freeze
|
232
210
|
|
233
211
|
CONNECTION_CLOSE = "Connection: close\r\n".freeze
|
234
212
|
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n".freeze
|
@@ -236,6 +214,8 @@ module Puma
|
|
236
214
|
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n".freeze
|
237
215
|
CLOSE_CHUNKED = "0\r\n\r\n".freeze
|
238
216
|
|
217
|
+
CHUNKED = "chunked".freeze
|
218
|
+
|
239
219
|
COLON = ": ".freeze
|
240
220
|
|
241
221
|
NEWLINE = "\n".freeze
|
@@ -243,5 +223,7 @@ module Puma
|
|
243
223
|
HIJACK_P = "rack.hijack?".freeze
|
244
224
|
HIJACK = "rack.hijack".freeze
|
245
225
|
HIJACK_IO = "rack.hijack_io".freeze
|
226
|
+
|
227
|
+
EARLY_HINTS = "rack.early_hints".freeze
|
246
228
|
end
|
247
229
|
end
|
data/lib/puma/control_cli.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'optparse'
|
2
|
-
require 'puma'
|
2
|
+
require 'puma/state_file'
|
3
3
|
require 'puma/const'
|
4
4
|
require 'puma/detect'
|
5
5
|
require 'puma/configuration'
|
@@ -9,7 +9,7 @@ require 'socket'
|
|
9
9
|
module Puma
|
10
10
|
class ControlCLI
|
11
11
|
|
12
|
-
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory}
|
12
|
+
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats}
|
13
13
|
|
14
14
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
15
15
|
@state = nil
|
@@ -69,6 +69,7 @@ module Puma
|
|
69
69
|
end
|
70
70
|
|
71
71
|
opts.order!(argv) { |a| opts.terminate a }
|
72
|
+
opts.parse!
|
72
73
|
|
73
74
|
@command = argv.shift
|
74
75
|
|
@@ -78,11 +79,12 @@ module Puma
|
|
78
79
|
end
|
79
80
|
|
80
81
|
if @config_file
|
81
|
-
config = Puma::Configuration.
|
82
|
-
|
83
|
-
@
|
82
|
+
config = Puma::Configuration.new({ config_files: [@config_file] }, {})
|
83
|
+
config.load
|
84
|
+
@state ||= config.options[:state]
|
85
|
+
@control_url ||= config.options[:control_url]
|
84
86
|
@control_auth_token ||= config.options[:control_auth_token]
|
85
|
-
@pidfile
|
87
|
+
@pidfile ||= config.options[:pidfile]
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
@@ -97,6 +99,7 @@ module Puma
|
|
97
99
|
|
98
100
|
rescue => e
|
99
101
|
@stdout.puts e.message
|
102
|
+
@stdout.puts e.backtrace
|
100
103
|
exit 1
|
101
104
|
end
|
102
105
|
|
@@ -167,7 +170,7 @@ module Puma
|
|
167
170
|
end
|
168
171
|
|
169
172
|
message "Command #{@command} sent success"
|
170
|
-
message response.last if @command == "stats"
|
173
|
+
message response.last if @command == "stats" || @command == "gc-stats"
|
171
174
|
end
|
172
175
|
|
173
176
|
@server.close
|
@@ -179,46 +182,45 @@ module Puma
|
|
179
182
|
end
|
180
183
|
|
181
184
|
begin
|
182
|
-
Process.getpgid @pid
|
183
|
-
rescue SystemCallError
|
184
|
-
if @command == "restart"
|
185
|
-
start
|
186
|
-
else
|
187
|
-
raise "No pid '#{@pid}' found"
|
188
|
-
end
|
189
|
-
end
|
190
185
|
|
191
|
-
|
192
|
-
|
193
|
-
|
186
|
+
case @command
|
187
|
+
when "restart"
|
188
|
+
Process.kill "SIGUSR2", @pid
|
194
189
|
|
195
|
-
|
196
|
-
|
190
|
+
when "halt"
|
191
|
+
Process.kill "QUIT", @pid
|
197
192
|
|
198
|
-
|
199
|
-
|
193
|
+
when "stop"
|
194
|
+
Process.kill "SIGTERM", @pid
|
200
195
|
|
201
|
-
|
202
|
-
|
203
|
-
|
196
|
+
when "stats"
|
197
|
+
puts "Stats not available via pid only"
|
198
|
+
return
|
204
199
|
|
205
|
-
|
206
|
-
|
207
|
-
|
200
|
+
when "reload-worker-directory"
|
201
|
+
puts "reload-worker-directory not available via pid only"
|
202
|
+
return
|
208
203
|
|
209
|
-
|
210
|
-
|
204
|
+
when "phased-restart"
|
205
|
+
Process.kill "SIGUSR1", @pid
|
211
206
|
|
212
|
-
|
213
|
-
|
214
|
-
|
207
|
+
else
|
208
|
+
return
|
209
|
+
end
|
210
|
+
|
211
|
+
rescue SystemCallError
|
212
|
+
if @command == "restart"
|
213
|
+
start
|
214
|
+
else
|
215
|
+
raise "No pid '#{@pid}' found"
|
216
|
+
end
|
215
217
|
end
|
216
218
|
|
217
219
|
message "Command #{@command} sent success"
|
218
220
|
end
|
219
221
|
|
220
222
|
def run
|
221
|
-
start if @command == "start"
|
223
|
+
return start if @command == "start"
|
222
224
|
|
223
225
|
prepare_configuration
|
224
226
|
|
@@ -230,6 +232,7 @@ module Puma
|
|
230
232
|
|
231
233
|
rescue => e
|
232
234
|
message e.message
|
235
|
+
message e.backtrace
|
233
236
|
exit 1
|
234
237
|
end
|
235
238
|
|
@@ -242,7 +245,7 @@ module Puma
|
|
242
245
|
run_args += ["-S", @state] if @state
|
243
246
|
run_args += ["-q"] if @quiet
|
244
247
|
run_args += ["--pidfile", @pidfile] if @pidfile
|
245
|
-
run_args += ["--control", @control_url] if @control_url
|
248
|
+
run_args += ["--control-url", @control_url] if @control_url
|
246
249
|
run_args += ["--control-token", @control_auth_token] if @control_auth_token
|
247
250
|
run_args += ["-C", @config_file] if @config_file
|
248
251
|
|
data/lib/puma/convenient.rb
CHANGED
@@ -3,12 +3,12 @@ require 'puma/configuration'
|
|
3
3
|
|
4
4
|
module Puma
|
5
5
|
def self.run(opts={})
|
6
|
-
cfg = Puma::Configuration.new do |
|
6
|
+
cfg = Puma::Configuration.new do |user_config|
|
7
7
|
if port = opts[:port]
|
8
|
-
|
8
|
+
user_config.port port
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
user_config.quiet
|
12
12
|
|
13
13
|
yield c
|
14
14
|
end
|
data/lib/puma/detect.rb
CHANGED
data/lib/puma/dsl.rb
CHANGED
@@ -1,20 +1,35 @@
|
|
1
1
|
module Puma
|
2
2
|
# The methods that are available for use inside the config file.
|
3
|
+
# These same methods are used in Puma cli and the rack handler
|
4
|
+
# internally.
|
3
5
|
#
|
6
|
+
# Used manually (via CLI class):
|
7
|
+
#
|
8
|
+
# config = Configuration.new({}) do |user_config|
|
9
|
+
# user_config.port 3001
|
10
|
+
# end
|
11
|
+
# config.load
|
12
|
+
#
|
13
|
+
# puts config.options[:binds]
|
14
|
+
# "tcp://127.0.0.1:3001"
|
15
|
+
#
|
16
|
+
# Used to load file:
|
17
|
+
#
|
18
|
+
# $ cat puma_config.rb
|
19
|
+
# port 3002
|
20
|
+
#
|
21
|
+
# config = Configuration.new(config_file: "puma_config.rb")
|
22
|
+
# config.load
|
23
|
+
#
|
24
|
+
# puts config.options[:binds]
|
25
|
+
# # => "tcp://127.0.0.1:3002"
|
26
|
+
#
|
27
|
+
# Detailed docs can be found in `examples/config.rb`
|
4
28
|
class DSL
|
5
29
|
include ConfigDefault
|
6
30
|
|
7
|
-
def self.load(options, cfg, path)
|
8
|
-
d = new(options, cfg)
|
9
|
-
d._load_from(path)
|
10
|
-
|
11
|
-
options
|
12
|
-
ensure
|
13
|
-
d._offer_plugins
|
14
|
-
end
|
15
|
-
|
16
31
|
def initialize(options, config)
|
17
|
-
@config
|
32
|
+
@config = config
|
18
33
|
@options = options
|
19
34
|
|
20
35
|
@plugins = []
|
@@ -40,36 +55,10 @@ module Puma
|
|
40
55
|
@plugins.clear
|
41
56
|
end
|
42
57
|
|
43
|
-
def _run(&blk)
|
44
|
-
blk.call self
|
45
|
-
ensure
|
46
|
-
_offer_plugins
|
47
|
-
end
|
48
|
-
|
49
58
|
def inject(&blk)
|
50
59
|
instance_eval(&blk)
|
51
60
|
end
|
52
61
|
|
53
|
-
# Load configuration from another named file. If the file name is absolute,
|
54
|
-
# load the file as an absolute path. Otherwise load it relative to the
|
55
|
-
# current config file.
|
56
|
-
#
|
57
|
-
def import(file)
|
58
|
-
if File.extname(file) == ""
|
59
|
-
file += ".rb"
|
60
|
-
end
|
61
|
-
|
62
|
-
if file[0,1] == "/"
|
63
|
-
path = file
|
64
|
-
elsif @path
|
65
|
-
path = File.join File.dirname(@path), file
|
66
|
-
else
|
67
|
-
raise "No original configuration path to import relative to"
|
68
|
-
end
|
69
|
-
|
70
|
-
DSL.new(@options, @config)._load_from(path)
|
71
|
-
end
|
72
|
-
|
73
62
|
def get(key,default=nil)
|
74
63
|
@options[key.to_sym] || default
|
75
64
|
end
|
@@ -115,15 +104,35 @@ module Puma
|
|
115
104
|
end
|
116
105
|
|
117
106
|
# Load additional configuration from a file
|
107
|
+
# Files get loaded later via Configuration#load
|
118
108
|
def load(file)
|
119
|
-
|
109
|
+
@options[:config_files] ||= []
|
110
|
+
@options[:config_files] << file
|
120
111
|
end
|
121
112
|
|
122
|
-
#
|
123
|
-
# protocols.
|
113
|
+
# Adds a binding for the server to +url+. tcp://, unix://, and ssl:// are the only accepted
|
114
|
+
# protocols. Use query parameters within the url to specify options.
|
115
|
+
#
|
116
|
+
# @note multiple urls can be bound to, calling `bind` does not overwrite previous bindings.
|
117
|
+
#
|
118
|
+
# @example Explicitly the socket backlog depth (default is 1024)
|
119
|
+
# bind('unix:///var/run/puma.sock?backlog=2048')
|
124
120
|
#
|
121
|
+
# @example Set up ssl cert
|
122
|
+
# bind('ssl://127.0.0.1:9292?key=key.key&cert=cert.pem')
|
123
|
+
#
|
124
|
+
# @example Prefer low-latency over higher throughput (via `Socket::TCP_NODELAY`)
|
125
|
+
# bind('tcp://0.0.0.0:9292?low_latency=true')
|
126
|
+
#
|
127
|
+
# @example Set socket permissions
|
128
|
+
# bind('unix:///var/run/puma.sock?umask=0111')
|
125
129
|
def bind(url)
|
126
|
-
|
130
|
+
@options[:binds] ||= []
|
131
|
+
@options[:binds] << url
|
132
|
+
end
|
133
|
+
|
134
|
+
def clear_binds!
|
135
|
+
@options[:binds] = []
|
127
136
|
end
|
128
137
|
|
129
138
|
# Define the TCP port to bind to. Use +bind+ for more advanced options.
|
@@ -133,6 +142,19 @@ module Puma
|
|
133
142
|
bind "tcp://#{host}:#{port}"
|
134
143
|
end
|
135
144
|
|
145
|
+
# Define how long persistent connections can be idle before puma closes
|
146
|
+
# them
|
147
|
+
#
|
148
|
+
def persistent_timeout(seconds)
|
149
|
+
@options[:persistent_timeout] = Integer(seconds)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Define how long the tcp socket stays open, if no data has been received
|
153
|
+
#
|
154
|
+
def first_data_timeout(seconds)
|
155
|
+
@options[:first_data_timeout] = Integer(seconds)
|
156
|
+
end
|
157
|
+
|
136
158
|
# Work around leaky apps that leave garbage in Thread locals
|
137
159
|
# across requests
|
138
160
|
#
|
@@ -147,7 +169,7 @@ module Puma
|
|
147
169
|
end
|
148
170
|
|
149
171
|
# When shutting down, drain the accept socket of pending
|
150
|
-
# connections and
|
172
|
+
# connections and process them. This loops over the accept
|
151
173
|
# socket until there are no more read events and then stops
|
152
174
|
# looking and waits for the requests to finish.
|
153
175
|
def drain_on_shutdown(which=true)
|
@@ -185,7 +207,8 @@ module Puma
|
|
185
207
|
# This can be called multiple times to add code each time.
|
186
208
|
#
|
187
209
|
def on_restart(&block)
|
188
|
-
|
210
|
+
@options[:on_restart] ||= []
|
211
|
+
@options[:on_restart] << block
|
189
212
|
end
|
190
213
|
|
191
214
|
# Command to use to restart puma. This should be just how to
|
@@ -231,6 +254,10 @@ module Puma
|
|
231
254
|
@options[:mode] = :tcp
|
232
255
|
end
|
233
256
|
|
257
|
+
def early_hints(answer=true)
|
258
|
+
@options[:early_hints] = answer
|
259
|
+
end
|
260
|
+
|
234
261
|
# Redirect STDOUT and STDERR to files specified.
|
235
262
|
def stdout_redirect(stdout=nil, stderr=nil, append=false)
|
236
263
|
@options[:redirect_stdout] = stdout
|
@@ -257,11 +284,13 @@ module Puma
|
|
257
284
|
end
|
258
285
|
|
259
286
|
def ssl_bind(host, port, opts)
|
287
|
+
verify = opts.fetch(:verify_mode, 'none')
|
288
|
+
|
260
289
|
if defined?(JRUBY_VERSION)
|
261
290
|
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
262
|
-
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}"
|
291
|
+
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}"
|
263
292
|
else
|
264
|
-
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}"
|
293
|
+
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&verify_mode=#{verify}"
|
265
294
|
end
|
266
295
|
end
|
267
296
|
|
@@ -288,7 +317,8 @@ module Puma
|
|
288
317
|
# This can be called multiple times to add hooks.
|
289
318
|
#
|
290
319
|
def before_fork(&block)
|
291
|
-
|
320
|
+
@options[:before_fork] ||= []
|
321
|
+
@options[:before_fork] << block
|
292
322
|
end
|
293
323
|
|
294
324
|
# *Cluster mode only* Code to run in a worker when it boots to setup
|
@@ -297,7 +327,8 @@ module Puma
|
|
297
327
|
# This can be called multiple times to add hooks.
|
298
328
|
#
|
299
329
|
def on_worker_boot(&block)
|
300
|
-
|
330
|
+
@options[:before_worker_boot] ||= []
|
331
|
+
@options[:before_worker_boot] << block
|
301
332
|
end
|
302
333
|
|
303
334
|
# *Cluster mode only* Code to run immediately before a worker shuts
|
@@ -308,7 +339,8 @@ module Puma
|
|
308
339
|
# This can be called multiple times to add hooks.
|
309
340
|
#
|
310
341
|
def on_worker_shutdown(&block)
|
311
|
-
|
342
|
+
@options[:before_worker_shutdown] ||= []
|
343
|
+
@options[:before_worker_shutdown] << block
|
312
344
|
end
|
313
345
|
|
314
346
|
# *Cluster mode only* Code to run in the master when it is
|
@@ -317,7 +349,8 @@ module Puma
|
|
317
349
|
# This can be called multiple times to add hooks.
|
318
350
|
#
|
319
351
|
def on_worker_fork(&block)
|
320
|
-
|
352
|
+
@options[:before_worker_fork] ||= []
|
353
|
+
@options[:before_worker_fork] << block
|
321
354
|
end
|
322
355
|
|
323
356
|
# *Cluster mode only* Code to run in the master after it starts
|
@@ -326,7 +359,8 @@ module Puma
|
|
326
359
|
# This can be called multiple times to add hooks.
|
327
360
|
#
|
328
361
|
def after_worker_fork(&block)
|
329
|
-
|
362
|
+
@options[:after_worker_fork] ||= []
|
363
|
+
@options[:after_worker_fork] = block
|
330
364
|
end
|
331
365
|
|
332
366
|
alias_method :after_worker_boot, :after_worker_fork
|
@@ -390,17 +424,17 @@ module Puma
|
|
390
424
|
# that have not checked in within the given +timeout+.
|
391
425
|
# This mitigates hung processes. Default value is 60 seconds.
|
392
426
|
def worker_timeout(timeout)
|
393
|
-
@options[:worker_timeout] = timeout
|
427
|
+
@options[:worker_timeout] = Integer(timeout)
|
394
428
|
end
|
395
429
|
|
396
430
|
# *Cluster mode only* Set the timeout for workers to boot
|
397
431
|
def worker_boot_timeout(timeout)
|
398
|
-
@options[:worker_boot_timeout] = timeout
|
432
|
+
@options[:worker_boot_timeout] = Integer(timeout)
|
399
433
|
end
|
400
434
|
|
401
435
|
# *Cluster mode only* Set the timeout for worker shutdown
|
402
436
|
def worker_shutdown_timeout(timeout)
|
403
|
-
@options[:worker_shutdown_timeout] = timeout
|
437
|
+
@options[:worker_shutdown_timeout] = Integer(timeout)
|
404
438
|
end
|
405
439
|
|
406
440
|
# When set to true (the default), workers accept all requests
|
@@ -468,10 +502,5 @@ module Puma
|
|
468
502
|
end
|
469
503
|
end
|
470
504
|
|
471
|
-
private
|
472
|
-
|
473
|
-
def _ary(key)
|
474
|
-
(@options.cur[key] ||= [])
|
475
|
-
end
|
476
505
|
end
|
477
506
|
end
|