puma 6.0.0 → 6.4.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 +4 -4
- data/History.md +184 -6
- data/LICENSE +0 -0
- data/README.md +58 -13
- data/bin/puma-wild +0 -0
- data/docs/architecture.md +0 -0
- data/docs/compile_options.md +0 -0
- data/docs/deployment.md +0 -0
- data/docs/fork_worker.md +0 -0
- 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/jungle/README.md +0 -0
- data/docs/jungle/rc.d/README.md +0 -0
- data/docs/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +12 -0
- data/docs/nginx.md +1 -1
- data/docs/plugins.md +0 -0
- data/docs/rails_dev_mode.md +0 -0
- data/docs/restart.md +0 -0
- data/docs/signals.md +0 -0
- data/docs/stats.md +0 -0
- data/docs/systemd.md +1 -2
- data/docs/testing_benchmarks_local_files.md +0 -0
- data/docs/testing_test_rackup_ci_files.md +0 -0
- data/ext/puma_http11/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/ext_help.h +0 -0
- data/ext/puma_http11/extconf.rb +0 -0
- data/ext/puma_http11/http11_parser.c +0 -0
- data/ext/puma_http11/http11_parser.h +0 -0
- data/ext/puma_http11/http11_parser.java.rl +0 -0
- data/ext/puma_http11/http11_parser.rl +0 -0
- data/ext/puma_http11/http11_parser_common.rl +0 -0
- data/ext/puma_http11/mini_ssl.c +91 -8
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +0 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +0 -0
- data/ext/puma_http11/puma_http11.c +0 -0
- data/lib/puma/app/status.rb +1 -1
- data/lib/puma/binder.rb +14 -11
- data/lib/puma/cli.rb +5 -1
- data/lib/puma/client.rb +53 -16
- data/lib/puma/cluster/worker.rb +5 -0
- data/lib/puma/cluster/worker_handle.rb +0 -0
- data/lib/puma/cluster.rb +5 -5
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +5 -1
- data/lib/puma/const.rb +129 -88
- data/lib/puma/control_cli.rb +12 -5
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +147 -7
- data/lib/puma/error_logger.rb +2 -1
- data/lib/puma/events.rb +0 -0
- data/lib/puma/io_buffer.rb +10 -0
- data/lib/puma/jruby_restart.rb +0 -0
- data/lib/puma/json_serialization.rb +0 -0
- data/lib/puma/launcher/bundle_pruner.rb +0 -0
- data/lib/puma/launcher.rb +9 -22
- data/lib/puma/log_writer.rb +14 -4
- data/lib/puma/minissl/context_builder.rb +1 -0
- data/lib/puma/minissl.rb +17 -0
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +0 -0
- data/lib/puma/plugin.rb +0 -0
- data/lib/puma/rack/builder.rb +2 -2
- data/lib/puma/rack/urlmap.rb +1 -1
- data/lib/puma/rack_default.rb +18 -3
- data/lib/puma/reactor.rb +17 -8
- data/lib/puma/request.rb +189 -125
- data/lib/puma/runner.rb +16 -1
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +74 -34
- data/lib/puma/single.rb +3 -1
- data/lib/puma/state_file.rb +0 -0
- data/lib/puma/thread_pool.rb +42 -7
- data/lib/puma/util.rb +0 -0
- data/lib/puma.rb +1 -3
- data/lib/rack/handler/puma.rb +113 -86
- data/tools/Dockerfile +0 -0
- data/tools/trickletest.rb +0 -0
- metadata +4 -3
- data/lib/puma/systemd.rb +0 -47
data/lib/puma/const.rb
CHANGED
@@ -5,7 +5,6 @@ module Puma
|
|
5
5
|
class UnsupportedOption < RuntimeError
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
8
|
# Every standard HTTP code mapped to the appropriate message. These are
|
10
9
|
# used so frequently that they are placed directly in Puma for easy
|
11
10
|
# access rather than Puma::Const itself.
|
@@ -19,6 +18,7 @@ module Puma
|
|
19
18
|
100 => 'Continue',
|
20
19
|
101 => 'Switching Protocols',
|
21
20
|
102 => 'Processing',
|
21
|
+
103 => 'Early Hints',
|
22
22
|
200 => 'OK',
|
23
23
|
201 => 'Created',
|
24
24
|
202 => 'Accepted',
|
@@ -50,16 +50,16 @@ module Puma
|
|
50
50
|
410 => 'Gone',
|
51
51
|
411 => 'Length Required',
|
52
52
|
412 => 'Precondition Failed',
|
53
|
-
413 => '
|
53
|
+
413 => 'Content Too Large',
|
54
54
|
414 => 'URI Too Long',
|
55
55
|
415 => 'Unsupported Media Type',
|
56
56
|
416 => 'Range Not Satisfiable',
|
57
57
|
417 => 'Expectation Failed',
|
58
|
-
418 => 'I\'m A Teapot',
|
59
58
|
421 => 'Misdirected Request',
|
60
|
-
422 => 'Unprocessable
|
59
|
+
422 => 'Unprocessable Content',
|
61
60
|
423 => 'Locked',
|
62
61
|
424 => 'Failed Dependency',
|
62
|
+
425 => 'Too Early',
|
63
63
|
426 => 'Upgrade Required',
|
64
64
|
428 => 'Precondition Required',
|
65
65
|
429 => 'Too Many Requests',
|
@@ -74,7 +74,7 @@ module Puma
|
|
74
74
|
506 => 'Variant Also Negotiates',
|
75
75
|
507 => 'Insufficient Storage',
|
76
76
|
508 => 'Loop Detected',
|
77
|
-
510 => 'Not Extended',
|
77
|
+
510 => 'Not Extended (OBSOLETED)',
|
78
78
|
511 => 'Network Authentication Required'
|
79
79
|
}.freeze
|
80
80
|
|
@@ -100,10 +100,10 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "6.
|
104
|
-
CODE_NAME = "
|
103
|
+
PUMA_VERSION = VERSION = "6.4.0"
|
104
|
+
CODE_NAME = "The Eagle of Durango"
|
105
105
|
|
106
|
-
PUMA_SERVER_STRING = [
|
106
|
+
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
107
107
|
|
108
108
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
109
109
|
|
@@ -112,28 +112,28 @@ module Puma
|
|
112
112
|
WRITE_TIMEOUT = 10
|
113
113
|
|
114
114
|
# The original URI requested by the client.
|
115
|
-
REQUEST_URI=
|
116
|
-
REQUEST_PATH =
|
117
|
-
QUERY_STRING =
|
118
|
-
CONTENT_LENGTH = "CONTENT_LENGTH"
|
115
|
+
REQUEST_URI= "REQUEST_URI"
|
116
|
+
REQUEST_PATH = "REQUEST_PATH"
|
117
|
+
QUERY_STRING = "QUERY_STRING"
|
118
|
+
CONTENT_LENGTH = "CONTENT_LENGTH"
|
119
119
|
|
120
|
-
PATH_INFO =
|
120
|
+
PATH_INFO = "PATH_INFO"
|
121
121
|
|
122
|
-
PUMA_TMP_BASE = "puma"
|
122
|
+
PUMA_TMP_BASE = "puma"
|
123
123
|
|
124
124
|
ERROR_RESPONSE = {
|
125
125
|
# Indicate that we couldn't parse the request
|
126
|
-
400 => "HTTP/1.1 400 Bad Request\r\n\r\n"
|
126
|
+
400 => "HTTP/1.1 400 Bad Request\r\n\r\n",
|
127
127
|
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
128
|
-
404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\
|
128
|
+
404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n",
|
129
129
|
# The standard empty 408 response for requests that timed out.
|
130
|
-
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\
|
130
|
+
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n\r\n",
|
131
131
|
# Indicate that there was an internal error, obviously.
|
132
|
-
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n"
|
132
|
+
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n",
|
133
133
|
# Incorrect or invalid header value
|
134
|
-
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n"
|
134
|
+
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n",
|
135
135
|
# A common header for indicating the server is too busy. Not used yet.
|
136
|
-
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\
|
136
|
+
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\n"
|
137
137
|
}.freeze
|
138
138
|
|
139
139
|
# The basic max request size we'll try to read.
|
@@ -146,95 +146,136 @@ module Puma
|
|
146
146
|
# Maximum request body size before it is moved out of memory and into a tempfile for reading.
|
147
147
|
MAX_BODY = MAX_HEADER
|
148
148
|
|
149
|
-
REQUEST_METHOD = "REQUEST_METHOD"
|
150
|
-
HEAD = "HEAD"
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
149
|
+
REQUEST_METHOD = "REQUEST_METHOD"
|
150
|
+
HEAD = "HEAD"
|
151
|
+
|
152
|
+
# based on https://www.rfc-editor.org/rfc/rfc9110.html#name-overview,
|
153
|
+
# with CONNECT removed, and PATCH added
|
154
|
+
SUPPORTED_HTTP_METHODS = %w[HEAD GET POST PUT DELETE OPTIONS TRACE PATCH].freeze
|
155
|
+
|
156
|
+
# list from https://www.iana.org/assignments/http-methods/http-methods.xhtml
|
157
|
+
# as of 04-May-23
|
158
|
+
IANA_HTTP_METHODS = %w[
|
159
|
+
ACL
|
160
|
+
BASELINE-CONTROL
|
161
|
+
BIND
|
162
|
+
CHECKIN
|
163
|
+
CHECKOUT
|
164
|
+
CONNECT
|
165
|
+
COPY
|
166
|
+
DELETE
|
167
|
+
GET
|
168
|
+
HEAD
|
169
|
+
LABEL
|
170
|
+
LINK
|
171
|
+
LOCK
|
172
|
+
MERGE
|
173
|
+
MKACTIVITY
|
174
|
+
MKCALENDAR
|
175
|
+
MKCOL
|
176
|
+
MKREDIRECTREF
|
177
|
+
MKWORKSPACE
|
178
|
+
MOVE
|
179
|
+
OPTIONS
|
180
|
+
ORDERPATCH
|
181
|
+
PATCH
|
182
|
+
POST
|
183
|
+
PRI
|
184
|
+
PROPFIND
|
185
|
+
PROPPATCH
|
186
|
+
PUT
|
187
|
+
REBIND
|
188
|
+
REPORT
|
189
|
+
SEARCH
|
190
|
+
TRACE
|
191
|
+
UNBIND
|
192
|
+
UNCHECKOUT
|
193
|
+
UNLINK
|
194
|
+
UNLOCK
|
195
|
+
UPDATE
|
196
|
+
UPDATEREDIRECTREF
|
197
|
+
VERSION-CONTROL
|
198
|
+
].freeze
|
199
|
+
|
159
200
|
# ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
|
160
|
-
LINE_END = "\r\n"
|
161
|
-
REMOTE_ADDR = "REMOTE_ADDR"
|
162
|
-
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
163
|
-
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL"
|
164
|
-
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME"
|
165
|
-
HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO"
|
201
|
+
LINE_END = "\r\n"
|
202
|
+
REMOTE_ADDR = "REMOTE_ADDR"
|
203
|
+
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
204
|
+
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL"
|
205
|
+
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME"
|
206
|
+
HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO"
|
166
207
|
|
167
|
-
SERVER_NAME = "SERVER_NAME"
|
168
|
-
SERVER_PORT = "SERVER_PORT"
|
169
|
-
HTTP_HOST = "HTTP_HOST"
|
170
|
-
PORT_80 = "80"
|
171
|
-
PORT_443 = "443"
|
172
|
-
LOCALHOST = "localhost"
|
173
|
-
LOCALHOST_IPV4 = "127.0.0.1"
|
174
|
-
LOCALHOST_IPV6 = "::1"
|
175
|
-
UNSPECIFIED_IPV4 = "0.0.0.0"
|
176
|
-
UNSPECIFIED_IPV6 = "::"
|
208
|
+
SERVER_NAME = "SERVER_NAME"
|
209
|
+
SERVER_PORT = "SERVER_PORT"
|
210
|
+
HTTP_HOST = "HTTP_HOST"
|
211
|
+
PORT_80 = "80"
|
212
|
+
PORT_443 = "443"
|
213
|
+
LOCALHOST = "localhost"
|
214
|
+
LOCALHOST_IPV4 = "127.0.0.1"
|
215
|
+
LOCALHOST_IPV6 = "::1"
|
216
|
+
UNSPECIFIED_IPV4 = "0.0.0.0"
|
217
|
+
UNSPECIFIED_IPV6 = "::"
|
177
218
|
|
178
|
-
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
179
|
-
HTTP_11 = "HTTP/1.1"
|
219
|
+
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
220
|
+
HTTP_11 = "HTTP/1.1"
|
180
221
|
|
181
|
-
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
182
|
-
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
183
|
-
CGI_VER = "CGI/1.2"
|
222
|
+
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
223
|
+
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
224
|
+
CGI_VER = "CGI/1.2"
|
184
225
|
|
185
|
-
STOP_COMMAND = "?"
|
186
|
-
HALT_COMMAND = "!"
|
187
|
-
RESTART_COMMAND = "R"
|
226
|
+
STOP_COMMAND = "?"
|
227
|
+
HALT_COMMAND = "!"
|
228
|
+
RESTART_COMMAND = "R"
|
188
229
|
|
189
|
-
RACK_INPUT = "rack.input"
|
190
|
-
RACK_URL_SCHEME = "rack.url_scheme"
|
191
|
-
RACK_AFTER_REPLY = "rack.after_reply"
|
192
|
-
PUMA_SOCKET = "puma.socket"
|
193
|
-
PUMA_CONFIG = "puma.config"
|
194
|
-
PUMA_PEERCERT = "puma.peercert"
|
230
|
+
RACK_INPUT = "rack.input"
|
231
|
+
RACK_URL_SCHEME = "rack.url_scheme"
|
232
|
+
RACK_AFTER_REPLY = "rack.after_reply"
|
233
|
+
PUMA_SOCKET = "puma.socket"
|
234
|
+
PUMA_CONFIG = "puma.config"
|
235
|
+
PUMA_PEERCERT = "puma.peercert"
|
195
236
|
|
196
|
-
HTTP = "http"
|
197
|
-
HTTPS = "https"
|
237
|
+
HTTP = "http"
|
238
|
+
HTTPS = "https"
|
198
239
|
|
199
|
-
HTTPS_KEY = "HTTPS"
|
240
|
+
HTTPS_KEY = "HTTPS"
|
200
241
|
|
201
|
-
HTTP_VERSION = "HTTP_VERSION"
|
202
|
-
HTTP_CONNECTION = "HTTP_CONNECTION"
|
203
|
-
HTTP_EXPECT = "HTTP_EXPECT"
|
204
|
-
CONTINUE = "100-continue"
|
242
|
+
HTTP_VERSION = "HTTP_VERSION"
|
243
|
+
HTTP_CONNECTION = "HTTP_CONNECTION"
|
244
|
+
HTTP_EXPECT = "HTTP_EXPECT"
|
245
|
+
CONTINUE = "100-continue"
|
205
246
|
|
206
|
-
HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n"
|
207
|
-
HTTP_11_200 = "HTTP/1.1 200 OK\r\n"
|
208
|
-
HTTP_10_200 = "HTTP/1.0 200 OK\r\n"
|
247
|
+
HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n"
|
248
|
+
HTTP_11_200 = "HTTP/1.1 200 OK\r\n"
|
249
|
+
HTTP_10_200 = "HTTP/1.0 200 OK\r\n"
|
209
250
|
|
210
|
-
CLOSE = "close"
|
211
|
-
KEEP_ALIVE = "keep-alive"
|
251
|
+
CLOSE = "close"
|
252
|
+
KEEP_ALIVE = "keep-alive"
|
212
253
|
|
213
|
-
CONTENT_LENGTH2 = "content-length"
|
214
|
-
CONTENT_LENGTH_S = "Content-Length: "
|
215
|
-
TRANSFER_ENCODING = "transfer-encoding"
|
216
|
-
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
254
|
+
CONTENT_LENGTH2 = "content-length"
|
255
|
+
CONTENT_LENGTH_S = "Content-Length: "
|
256
|
+
TRANSFER_ENCODING = "transfer-encoding"
|
257
|
+
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
217
258
|
|
218
|
-
CONNECTION_CLOSE = "Connection: close\r\n"
|
219
|
-
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
|
259
|
+
CONNECTION_CLOSE = "Connection: close\r\n"
|
260
|
+
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
|
220
261
|
|
221
|
-
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
|
222
|
-
CLOSE_CHUNKED = "0\r\n\r\n"
|
262
|
+
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
|
263
|
+
CLOSE_CHUNKED = "0\r\n\r\n"
|
223
264
|
|
224
|
-
CHUNKED = "chunked"
|
265
|
+
CHUNKED = "chunked"
|
225
266
|
|
226
|
-
COLON = ": "
|
267
|
+
COLON = ": "
|
227
268
|
|
228
|
-
NEWLINE = "\n"
|
269
|
+
NEWLINE = "\n"
|
229
270
|
|
230
|
-
HIJACK_P = "rack.hijack?"
|
231
|
-
HIJACK = "rack.hijack"
|
232
|
-
HIJACK_IO = "rack.hijack_io"
|
271
|
+
HIJACK_P = "rack.hijack?"
|
272
|
+
HIJACK = "rack.hijack"
|
273
|
+
HIJACK_IO = "rack.hijack_io"
|
233
274
|
|
234
|
-
EARLY_HINTS = "rack.early_hints"
|
275
|
+
EARLY_HINTS = "rack.early_hints"
|
235
276
|
|
236
277
|
# Illegal character in the key or value of response header
|
237
|
-
DQUOTE = "\""
|
278
|
+
DQUOTE = "\""
|
238
279
|
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
239
280
|
ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
|
240
281
|
# header values can contain HTAB?
|
data/lib/puma/control_cli.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'optparse'
|
4
|
-
require_relative 'state_file'
|
5
4
|
require_relative 'const'
|
6
5
|
require_relative 'detect'
|
7
|
-
require_relative 'configuration'
|
8
6
|
require 'uri'
|
9
7
|
require 'socket'
|
10
8
|
|
@@ -126,6 +124,9 @@ module Puma
|
|
126
124
|
end
|
127
125
|
|
128
126
|
if @config_file
|
127
|
+
require_relative 'configuration'
|
128
|
+
require_relative 'log_writer'
|
129
|
+
|
129
130
|
config = Puma::Configuration.new({ config_files: [@config_file] }, {})
|
130
131
|
config.load
|
131
132
|
@state ||= config.options[:state]
|
@@ -149,6 +150,8 @@ module Puma
|
|
149
150
|
raise "State file not found: #{@state}"
|
150
151
|
end
|
151
152
|
|
153
|
+
require_relative 'state_file'
|
154
|
+
|
152
155
|
sf = Puma::StateFile.new
|
153
156
|
sf.load @state
|
154
157
|
|
@@ -164,22 +167,26 @@ module Puma
|
|
164
167
|
def send_request
|
165
168
|
uri = URI.parse @control_url
|
166
169
|
|
170
|
+
host = uri.host
|
171
|
+
|
167
172
|
# create server object by scheme
|
168
173
|
server =
|
169
174
|
case uri.scheme
|
170
175
|
when 'ssl'
|
171
176
|
require 'openssl'
|
177
|
+
host = host[1..-2] if host&.start_with? '['
|
172
178
|
OpenSSL::SSL::SSLSocket.new(
|
173
|
-
TCPSocket.new(
|
179
|
+
TCPSocket.new(host, uri.port),
|
174
180
|
OpenSSL::SSL::SSLContext.new)
|
175
181
|
.tap { |ssl| ssl.sync_close = true } # default is false
|
176
182
|
.tap(&:connect)
|
177
183
|
when 'tcp'
|
178
|
-
|
184
|
+
host = host[1..-2] if host&.start_with? '['
|
185
|
+
TCPSocket.new host, uri.port
|
179
186
|
when 'unix'
|
180
187
|
# check for abstract UNIXSocket
|
181
188
|
UNIXSocket.new(@control_url.start_with?('unix://@') ?
|
182
|
-
"\0#{
|
189
|
+
"\0#{host}#{uri.path}" : "#{host}#{uri.path}")
|
183
190
|
else
|
184
191
|
raise "Invalid scheme: #{uri.scheme}"
|
185
192
|
end
|
data/lib/puma/detect.rb
CHANGED
data/lib/puma/dsl.rb
CHANGED
@@ -65,6 +65,7 @@ module Puma
|
|
65
65
|
|
66
66
|
ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
|
67
67
|
|
68
|
+
low_latency_str = opts.key?(:low_latency) ? "&low_latency=#{opts[:low_latency]}" : ''
|
68
69
|
backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
|
69
70
|
|
70
71
|
if defined?(JRUBY_VERSION)
|
@@ -88,6 +89,7 @@ module Puma
|
|
88
89
|
|
89
90
|
cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(cert)}" : nil
|
90
91
|
key_flags = (key = opts[:key]) ? "&key=#{Puma::Util.escape(key)}" : nil
|
92
|
+
password_flags = (password_command = opts[:key_password_command]) ? "&key_password_command=#{Puma::Util.escape(password_command)}" : nil
|
91
93
|
|
92
94
|
reuse_flag =
|
93
95
|
if (reuse = opts[:reuse])
|
@@ -113,8 +115,8 @@ module Puma
|
|
113
115
|
nil
|
114
116
|
end
|
115
117
|
|
116
|
-
"ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{ssl_cipher_filter}" \
|
117
|
-
"#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
|
118
|
+
"ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{password_flags}#{ssl_cipher_filter}" \
|
119
|
+
"#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}#{low_latency_str}"
|
118
120
|
end
|
119
121
|
end
|
120
122
|
|
@@ -250,6 +252,7 @@ module Puma
|
|
250
252
|
#
|
251
253
|
# * Set the socket backlog depth with +backlog+, default is 1024.
|
252
254
|
# * Set up an SSL certificate with +key+ & +cert+.
|
255
|
+
# * Set up an SSL certificate for mTLS with +key+, +cert+, +ca+ and +verify_mode+.
|
253
256
|
# * Set whether to optimize for low latency instead of throughput with
|
254
257
|
# +low_latency+, default is to not optimize for low latency. This is done
|
255
258
|
# via +Socket::TCP_NODELAY+.
|
@@ -259,6 +262,8 @@ module Puma
|
|
259
262
|
# bind 'unix:///var/run/puma.sock?backlog=512'
|
260
263
|
# @example SSL cert
|
261
264
|
# bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
|
265
|
+
# @example SSL cert for mutual TLS (mTLS)
|
266
|
+
# bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem&ca=ca.pem&verify_mode=force_peer'
|
262
267
|
# @example Disable optimization for low latency
|
263
268
|
# bind 'tcp://0.0.0.0:9292?low_latency=false'
|
264
269
|
# @example Socket permissions
|
@@ -310,16 +315,22 @@ module Puma
|
|
310
315
|
bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
|
311
316
|
end
|
312
317
|
|
318
|
+
# Define how long the tcp socket stays open, if no data has been received.
|
319
|
+
# @see Puma::Server.new
|
320
|
+
def first_data_timeout(seconds)
|
321
|
+
@options[:first_data_timeout] = Integer(seconds)
|
322
|
+
end
|
323
|
+
|
313
324
|
# Define how long persistent connections can be idle before Puma closes them.
|
314
325
|
# @see Puma::Server.new
|
315
326
|
def persistent_timeout(seconds)
|
316
327
|
@options[:persistent_timeout] = Integer(seconds)
|
317
328
|
end
|
318
329
|
|
319
|
-
#
|
330
|
+
# If a new request is not received within this number of seconds, begin shutting down.
|
320
331
|
# @see Puma::Server.new
|
321
|
-
def
|
322
|
-
@options[:
|
332
|
+
def idle_timeout(seconds)
|
333
|
+
@options[:idle_timeout] = Integer(seconds)
|
323
334
|
end
|
324
335
|
|
325
336
|
# Work around leaky apps that leave garbage in Thread locals
|
@@ -415,6 +426,11 @@ module Puma
|
|
415
426
|
@options[:log_requests] = which
|
416
427
|
end
|
417
428
|
|
429
|
+
# Pass in a custom logging class instance
|
430
|
+
def custom_logger(custom_logger)
|
431
|
+
@options[:custom_logger] = custom_logger
|
432
|
+
end
|
433
|
+
|
418
434
|
# Show debugging info
|
419
435
|
#
|
420
436
|
def debug
|
@@ -500,6 +516,12 @@ module Puma
|
|
500
516
|
# `true`, which sets reuse 'on' with default values, or a hash, with `:size`
|
501
517
|
# and/or `:timeout` keys, each with integer values.
|
502
518
|
#
|
519
|
+
# The `cert:` options hash parameter can be the path to a certificate
|
520
|
+
# file including all intermediate certificates in PEM format.
|
521
|
+
#
|
522
|
+
# The `cert_pem:` options hash parameter can be String containing the
|
523
|
+
# cerificate and all intermediate certificates in PEM format.
|
524
|
+
#
|
503
525
|
# @example
|
504
526
|
# ssl_bind '127.0.0.1', '9292', {
|
505
527
|
# cert: path_to_cert,
|
@@ -581,6 +603,11 @@ module Puma
|
|
581
603
|
@options[:silence_single_worker_warning] = true
|
582
604
|
end
|
583
605
|
|
606
|
+
# Disable warning message when running single mode with callback hook defined.
|
607
|
+
def silence_fork_callback_warning
|
608
|
+
@options[:silence_fork_callback_warning] = true
|
609
|
+
end
|
610
|
+
|
584
611
|
# Code to run immediately before master process
|
585
612
|
# forks workers (once on boot). These hooks can block if necessary
|
586
613
|
# to wait for background operations unknown to Puma to finish before
|
@@ -596,6 +623,8 @@ module Puma
|
|
596
623
|
# puts "Starting workers..."
|
597
624
|
# end
|
598
625
|
def before_fork(&block)
|
626
|
+
warn_if_in_single_mode('before_fork')
|
627
|
+
|
599
628
|
@options[:before_fork] ||= []
|
600
629
|
@options[:before_fork] << block
|
601
630
|
end
|
@@ -611,6 +640,8 @@ module Puma
|
|
611
640
|
# puts 'Before worker boot...'
|
612
641
|
# end
|
613
642
|
def on_worker_boot(key = nil, &block)
|
643
|
+
warn_if_in_single_mode('on_worker_boot')
|
644
|
+
|
614
645
|
process_hook :before_worker_boot, key, block, 'on_worker_boot'
|
615
646
|
end
|
616
647
|
|
@@ -627,6 +658,8 @@ module Puma
|
|
627
658
|
# puts 'On worker shutdown...'
|
628
659
|
# end
|
629
660
|
def on_worker_shutdown(key = nil, &block)
|
661
|
+
warn_if_in_single_mode('on_worker_shutdown')
|
662
|
+
|
630
663
|
process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
|
631
664
|
end
|
632
665
|
|
@@ -641,6 +674,8 @@ module Puma
|
|
641
674
|
# puts 'Before worker fork...'
|
642
675
|
# end
|
643
676
|
def on_worker_fork(&block)
|
677
|
+
warn_if_in_single_mode('on_worker_fork')
|
678
|
+
|
644
679
|
process_hook :before_worker_fork, nil, block, 'on_worker_fork'
|
645
680
|
end
|
646
681
|
|
@@ -655,11 +690,23 @@ module Puma
|
|
655
690
|
# puts 'After worker fork...'
|
656
691
|
# end
|
657
692
|
def after_worker_fork(&block)
|
693
|
+
warn_if_in_single_mode('after_worker_fork')
|
694
|
+
|
658
695
|
process_hook :after_worker_fork, nil, block, 'after_worker_fork'
|
659
696
|
end
|
660
697
|
|
661
698
|
alias_method :after_worker_boot, :after_worker_fork
|
662
699
|
|
700
|
+
# Code to run after puma is booted (works for both: single and clustered)
|
701
|
+
#
|
702
|
+
# @example
|
703
|
+
# on_booted do
|
704
|
+
# puts 'After booting...'
|
705
|
+
# end
|
706
|
+
def on_booted(&block)
|
707
|
+
@config.options[:events].on_booted(&block)
|
708
|
+
end
|
709
|
+
|
663
710
|
# When `fork_worker` is enabled, code to run in Worker 0
|
664
711
|
# before all other workers are re-forked from this process,
|
665
712
|
# after the server has temporarily stopped serving requests
|
@@ -682,6 +729,40 @@ module Puma
|
|
682
729
|
process_hook :before_refork, key, block, 'on_refork'
|
683
730
|
end
|
684
731
|
|
732
|
+
# Code to run immediately before a thread starts. The worker does not
|
733
|
+
# start new threads until this code finishes.
|
734
|
+
#
|
735
|
+
# This hook is useful for doing something when a thread
|
736
|
+
# starts.
|
737
|
+
#
|
738
|
+
# This can be called multiple times to add several hooks.
|
739
|
+
#
|
740
|
+
# @example
|
741
|
+
# on_thread_start do
|
742
|
+
# puts 'On thread start...'
|
743
|
+
# end
|
744
|
+
def on_thread_start(&block)
|
745
|
+
@options[:before_thread_start] ||= []
|
746
|
+
@options[:before_thread_start] << block
|
747
|
+
end
|
748
|
+
|
749
|
+
# Code to run immediately before a thread exits. The worker does not
|
750
|
+
# accept new requests until this code finishes.
|
751
|
+
#
|
752
|
+
# This hook is useful for cleaning up thread local resources when a thread
|
753
|
+
# is trimmed.
|
754
|
+
#
|
755
|
+
# This can be called multiple times to add several hooks.
|
756
|
+
#
|
757
|
+
# @example
|
758
|
+
# on_thread_exit do
|
759
|
+
# puts 'On thread exit...'
|
760
|
+
# end
|
761
|
+
def on_thread_exit(&block)
|
762
|
+
@options[:before_thread_exit] ||= []
|
763
|
+
@options[:before_thread_exit] << block
|
764
|
+
end
|
765
|
+
|
685
766
|
# Code to run out-of-band when the worker is idle.
|
686
767
|
# These hooks run immediately after a request has finished
|
687
768
|
# processing and there are no busy threads on the worker.
|
@@ -813,7 +894,8 @@ module Puma
|
|
813
894
|
# not a request timeout, it is to protect against a hung or dead process.
|
814
895
|
# Setting this value will not protect against slow requests.
|
815
896
|
#
|
816
|
-
#
|
897
|
+
# This value must be greater than worker_check_interval.
|
898
|
+
# The default value is 60 seconds.
|
817
899
|
#
|
818
900
|
# @note Cluster mode only.
|
819
901
|
# @example
|
@@ -1019,6 +1101,51 @@ module Puma
|
|
1019
1101
|
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
1020
1102
|
end
|
1021
1103
|
|
1104
|
+
# Specify how big the request payload should be, in bytes.
|
1105
|
+
# This limit is compared against Content-Length HTTP header.
|
1106
|
+
# If the payload size (CONTENT_LENGTH) is larger than http_content_length_limit,
|
1107
|
+
# HTTP 413 status code is returned.
|
1108
|
+
#
|
1109
|
+
# When no Content-Length http header is present, it is compared against the
|
1110
|
+
# size of the body of the request.
|
1111
|
+
#
|
1112
|
+
# The default value for http_content_length_limit is nil.
|
1113
|
+
def http_content_length_limit(limit)
|
1114
|
+
@options[:http_content_length_limit] = limit
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
# Supported http methods, which will replace `Puma::Const::SUPPORTED_HTTP_METHODS`.
|
1118
|
+
# The value of `:any` will allows all methods, otherwise, the value must be
|
1119
|
+
# an array of strings. Note that methods are all uppercase.
|
1120
|
+
#
|
1121
|
+
# `Puma::Const::SUPPORTED_HTTP_METHODS` is conservative, if you want a
|
1122
|
+
# complete set of methods, the methods defined by the
|
1123
|
+
# [IANA Method Registry](https://www.iana.org/assignments/http-methods/http-methods.xhtml)
|
1124
|
+
# are pre-defined as the constant `Puma::Const::IANA_HTTP_METHODS`.
|
1125
|
+
#
|
1126
|
+
# @note If the `methods` value is `:any`, no method check with be performed,
|
1127
|
+
# similar to Puma v5 and earlier.
|
1128
|
+
#
|
1129
|
+
# @example Adds 'PROPFIND' to existing supported methods
|
1130
|
+
# supported_http_methods(Puma::Const::SUPPORTED_HTTP_METHODS + ['PROPFIND'])
|
1131
|
+
# @example Restricts methods to the array elements
|
1132
|
+
# supported_http_methods %w[HEAD GET POST PUT DELETE OPTIONS PROPFIND]
|
1133
|
+
# @example Restricts methods to the methods in the IANA Registry
|
1134
|
+
# supported_http_methods Puma::Const::IANA_HTTP_METHODS
|
1135
|
+
# @example Allows any method
|
1136
|
+
# supported_http_methods :any
|
1137
|
+
#
|
1138
|
+
def supported_http_methods(methods)
|
1139
|
+
if methods == :any
|
1140
|
+
@options[:supported_http_methods] = :any
|
1141
|
+
elsif Array === methods && methods == (ary = methods.grep(String).uniq) &&
|
1142
|
+
!ary.empty?
|
1143
|
+
@options[:supported_http_methods] = ary
|
1144
|
+
else
|
1145
|
+
raise "supported_http_methods must be ':any' or a unique array of strings"
|
1146
|
+
end
|
1147
|
+
end
|
1148
|
+
|
1022
1149
|
private
|
1023
1150
|
|
1024
1151
|
# To avoid adding cert_pem and key_pem as URI params, we store them on the
|
@@ -1046,7 +1173,20 @@ module Puma
|
|
1046
1173
|
elsif key.nil?
|
1047
1174
|
@options[options_key] << block
|
1048
1175
|
else
|
1049
|
-
raise "'#{
|
1176
|
+
raise "'#{meth}' key must be String or Symbol"
|
1177
|
+
end
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
def warn_if_in_single_mode(hook_name)
|
1181
|
+
return if @options[:silence_fork_callback_warning]
|
1182
|
+
|
1183
|
+
if (@options[:workers] || 0) == 0
|
1184
|
+
log_string =
|
1185
|
+
"Warning: You specified code to run in a `#{hook_name}` block, " \
|
1186
|
+
"but Puma is not configured to run in cluster mode (worker count > 0 ), " \
|
1187
|
+
"so your `#{hook_name}` block did not run"
|
1188
|
+
|
1189
|
+
LogWriter.stdio.log(log_string)
|
1050
1190
|
end
|
1051
1191
|
end
|
1052
1192
|
end
|
data/lib/puma/error_logger.rb
CHANGED
@@ -102,7 +102,8 @@ module Puma
|
|
102
102
|
@ioerr.is_a?(IO) and @ioerr.wait_writable(1)
|
103
103
|
@ioerr.write "#{w_str}\n"
|
104
104
|
@ioerr.flush unless @ioerr.sync
|
105
|
-
rescue Errno::EPIPE, Errno::EBADF, IOError
|
105
|
+
rescue Errno::EPIPE, Errno::EBADF, IOError, Errno::EINVAL
|
106
|
+
# 'Invalid argument' (Errno::EINVAL) may be raised by flush
|
106
107
|
end
|
107
108
|
end
|
108
109
|
rescue ThreadError
|
data/lib/puma/events.rb
CHANGED
File without changes
|