puma 6.6.0 → 8.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +309 -5
- data/README.md +41 -42
- data/docs/5.0-Upgrade.md +98 -0
- data/docs/6.0-Upgrade.md +56 -0
- data/docs/7.0-Upgrade.md +52 -0
- data/docs/8.0-Upgrade.md +100 -0
- data/docs/deployment.md +58 -23
- data/docs/fork_worker.md +5 -5
- data/docs/grpc.md +62 -0
- data/docs/images/favicon.svg +1 -0
- data/docs/images/running-puma.svg +1 -0
- data/docs/images/standard-logo.svg +1 -0
- data/docs/jungle/README.md +1 -1
- data/docs/kubernetes.md +11 -16
- data/docs/plugins.md +2 -2
- data/docs/restart.md +2 -2
- data/docs/signals.md +21 -21
- data/docs/stats.md +4 -3
- data/docs/systemd.md +4 -4
- data/ext/puma_http11/extconf.rb +2 -17
- data/ext/puma_http11/http11_parser.java.rl +51 -65
- data/ext/puma_http11/mini_ssl.c +18 -8
- data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +174 -102
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +71 -85
- data/ext/puma_http11/puma_http11.c +122 -118
- data/lib/puma/app/status.rb +10 -2
- data/lib/puma/binder.rb +12 -10
- data/lib/puma/cli.rb +4 -6
- data/lib/puma/client.rb +205 -131
- data/lib/puma/client_env.rb +171 -0
- data/lib/puma/cluster/worker.rb +17 -17
- data/lib/puma/cluster/worker_handle.rb +38 -7
- data/lib/puma/cluster.rb +44 -30
- data/lib/puma/cluster_accept_loop_delay.rb +91 -0
- data/lib/puma/commonlogger.rb +3 -3
- data/lib/puma/configuration.rb +173 -58
- data/lib/puma/const.rb +11 -11
- data/lib/puma/control_cli.rb +7 -3
- data/lib/puma/detect.rb +13 -0
- data/lib/puma/dsl.rb +225 -108
- data/lib/puma/error_logger.rb +3 -1
- data/lib/puma/events.rb +25 -10
- data/lib/puma/io_buffer.rb +8 -4
- data/lib/puma/launcher/bundle_pruner.rb +3 -5
- data/lib/puma/launcher.rb +57 -53
- data/lib/puma/log_writer.rb +8 -2
- data/lib/puma/minissl.rb +0 -1
- data/lib/puma/plugin/systemd.rb +3 -3
- data/lib/puma/rack/urlmap.rb +1 -1
- data/lib/puma/reactor.rb +19 -13
- data/lib/puma/{request.rb → response.rb} +56 -212
- data/lib/puma/runner.rb +9 -18
- data/lib/puma/server.rb +182 -97
- data/lib/puma/server_plugin_control.rb +32 -0
- data/lib/puma/single.rb +7 -4
- data/lib/puma/state_file.rb +3 -2
- data/lib/puma/thread_pool.rb +170 -99
- data/lib/puma/util.rb +0 -7
- data/lib/puma.rb +10 -0
- data/lib/rack/handler/puma.rb +3 -3
- data/tools/Dockerfile +15 -5
- metadata +19 -7
- data/ext/puma_http11/ext_help.h +0 -15
|
@@ -12,7 +12,7 @@ module Puma
|
|
|
12
12
|
# #handle_request, which is called in Server#process_client.
|
|
13
13
|
# @version 5.0.3
|
|
14
14
|
#
|
|
15
|
-
module
|
|
15
|
+
module Response # :nodoc:
|
|
16
16
|
|
|
17
17
|
# Single element array body: smaller bodies are written to io_buffer first,
|
|
18
18
|
# then a single write from io_buffer. Larger sizes are written separately.
|
|
@@ -36,42 +36,28 @@ module Puma
|
|
|
36
36
|
# Takes the request contained in +client+, invokes the Rack application to construct
|
|
37
37
|
# the response and writes it back to +client.io+.
|
|
38
38
|
#
|
|
39
|
-
# It'll return +
|
|
39
|
+
# It'll return +:close+ when the connection is closed, this doesn't mean
|
|
40
40
|
# that the response wasn't successful.
|
|
41
41
|
#
|
|
42
|
+
# It'll return +:keep_alive+ if the connection is a pipeline or keep-alive connection.
|
|
43
|
+
# Which may contain additional requests.
|
|
44
|
+
#
|
|
42
45
|
# It'll return +:async+ if the connection remains open but will be handled
|
|
43
46
|
# elsewhere, i.e. the connection has been hijacked by the Rack application.
|
|
44
47
|
#
|
|
45
48
|
# Finally, it'll return +true+ on keep-alive connections.
|
|
49
|
+
# @param processor [Puma::ThreadPool::ProcessorThread]
|
|
46
50
|
# @param client [Puma::Client]
|
|
47
51
|
# @param requests [Integer]
|
|
48
|
-
# @return [
|
|
49
|
-
|
|
50
|
-
def handle_request(client, requests)
|
|
52
|
+
# @return [:close, :keep_alive, :async]
|
|
53
|
+
def handle_request(processor, client, requests)
|
|
51
54
|
env = client.env
|
|
52
55
|
io_buffer = client.io_buffer
|
|
53
56
|
socket = client.io # io may be a MiniSSL::Socket
|
|
54
57
|
app_body = nil
|
|
58
|
+
error = nil
|
|
55
59
|
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
if client.http_content_length_limit_exceeded
|
|
59
|
-
return prepare_response(413, {}, ["Payload Too Large"], requests, client)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
normalize_env env, client
|
|
63
|
-
|
|
64
|
-
env[PUMA_SOCKET] = socket
|
|
65
|
-
|
|
66
|
-
if env[HTTPS_KEY] && socket.peercert
|
|
67
|
-
env[PUMA_PEERCERT] = socket.peercert
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
env[HIJACK_P] = true
|
|
71
|
-
env[HIJACK] = client
|
|
72
|
-
|
|
73
|
-
env[RACK_INPUT] = client.body
|
|
74
|
-
env[RACK_URL_SCHEME] ||= default_server_port(env) == PORT_443 ? HTTPS : HTTP
|
|
60
|
+
return :close if closed_socket?(socket)
|
|
75
61
|
|
|
76
62
|
if @early_hints
|
|
77
63
|
env[EARLY_HINTS] = lambda { |headers|
|
|
@@ -86,21 +72,11 @@ module Puma
|
|
|
86
72
|
}
|
|
87
73
|
end
|
|
88
74
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
# A rack extension. If the app writes #call'ables to this
|
|
92
|
-
# array, we will invoke them when the request is done.
|
|
93
|
-
#
|
|
94
|
-
env[RACK_AFTER_REPLY] ||= []
|
|
75
|
+
env["puma.mark_as_io_bound"] = -> { processor.mark_as_io_thread! }
|
|
95
76
|
|
|
96
77
|
begin
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
@app.call(env)
|
|
100
|
-
end
|
|
101
|
-
else
|
|
102
|
-
@log_writer.log "Unsupported HTTP method used: #{env[REQUEST_METHOD]}"
|
|
103
|
-
status, headers, app_body = [501, {}, ["#{env[REQUEST_METHOD]} method is not supported"]]
|
|
78
|
+
status, headers, app_body = @thread_pool.with_force_shutdown do
|
|
79
|
+
@app.call(env)
|
|
104
80
|
end
|
|
105
81
|
|
|
106
82
|
# app_body needs to always be closed, hold value in case lowlevel_error
|
|
@@ -119,28 +95,40 @@ module Puma
|
|
|
119
95
|
|
|
120
96
|
return :async
|
|
121
97
|
end
|
|
122
|
-
rescue ThreadPool::ForceShutdown =>
|
|
123
|
-
@log_writer.unknown_error
|
|
98
|
+
rescue ThreadPool::ForceShutdown => error
|
|
99
|
+
@log_writer.unknown_error error, client, "Rack app"
|
|
124
100
|
@log_writer.log "Detected force shutdown of a thread"
|
|
125
101
|
|
|
126
|
-
status, headers, res_body = lowlevel_error(
|
|
127
|
-
rescue Exception =>
|
|
128
|
-
@log_writer.unknown_error
|
|
102
|
+
status, headers, res_body = lowlevel_error(error, env, 503)
|
|
103
|
+
rescue Exception => error
|
|
104
|
+
@log_writer.unknown_error error, client, "Rack app"
|
|
129
105
|
|
|
130
|
-
status, headers, res_body = lowlevel_error(
|
|
106
|
+
status, headers, res_body = lowlevel_error(error, env, 500)
|
|
131
107
|
end
|
|
132
108
|
prepare_response(status, headers, res_body, requests, client)
|
|
133
109
|
ensure
|
|
134
110
|
io_buffer.reset
|
|
135
|
-
uncork_socket client.io
|
|
136
111
|
app_body.close if app_body.respond_to? :close
|
|
137
112
|
client&.tempfile_close
|
|
138
|
-
after_reply = env[RACK_AFTER_REPLY]
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
113
|
+
if after_reply = env[RACK_AFTER_REPLY]
|
|
114
|
+
after_reply.each do |o|
|
|
115
|
+
begin
|
|
116
|
+
o.call
|
|
117
|
+
rescue StandardError => e
|
|
118
|
+
@log_writer.debug_error e
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
if response_finished = env[RACK_RESPONSE_FINISHED]
|
|
124
|
+
response_finished.reverse_each do |o|
|
|
125
|
+
begin
|
|
126
|
+
o.call(env, status, headers, error)
|
|
127
|
+
rescue StandardError => e
|
|
128
|
+
@log_writer.debug_error e
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
144
132
|
end
|
|
145
133
|
|
|
146
134
|
# Assembles the headers and prepares the body for actually sending the
|
|
@@ -152,26 +140,16 @@ module Puma
|
|
|
152
140
|
# a call to `Server#lowlevel_error`
|
|
153
141
|
# @param requests [Integer] number of inline requests handled
|
|
154
142
|
# @param client [Puma::Client]
|
|
155
|
-
# @return [
|
|
143
|
+
# @return [:close, :keep_alive, :async]
|
|
156
144
|
def prepare_response(status, headers, res_body, requests, client)
|
|
157
145
|
env = client.env
|
|
158
146
|
socket = client.io
|
|
159
147
|
io_buffer = client.io_buffer
|
|
160
148
|
|
|
161
|
-
return
|
|
149
|
+
return :close if closed_socket?(socket)
|
|
162
150
|
|
|
163
151
|
# Close the connection after a reasonable number of inline requests
|
|
164
|
-
|
|
165
|
-
# This allows Puma to service connections fairly when the number
|
|
166
|
-
# of concurrent connections exceeds the size of the threadpool.
|
|
167
|
-
force_keep_alive = if @enable_keep_alives
|
|
168
|
-
requests < @max_fast_inline ||
|
|
169
|
-
@thread_pool.busy_threads < @max_threads ||
|
|
170
|
-
!client.listener.to_io.wait_readable(0)
|
|
171
|
-
else
|
|
172
|
-
# Always set force_keep_alive to false if the server has keep-alives not enabled.
|
|
173
|
-
false
|
|
174
|
-
end
|
|
152
|
+
force_keep_alive = @enable_keep_alives && client.requests_served < @max_keep_alive
|
|
175
153
|
|
|
176
154
|
resp_info = str_headers(env, status, headers, res_body, io_buffer, force_keep_alive)
|
|
177
155
|
|
|
@@ -191,7 +169,8 @@ module Puma
|
|
|
191
169
|
elsif res_body.is_a?(File) && res_body.respond_to?(:size)
|
|
192
170
|
body = res_body
|
|
193
171
|
content_length = body.size
|
|
194
|
-
elsif res_body.respond_to?(:to_path) &&
|
|
172
|
+
elsif res_body.respond_to?(:to_path) && (fn = res_body.to_path) &&
|
|
173
|
+
File.readable?(fn)
|
|
195
174
|
body = File.open fn, 'rb'
|
|
196
175
|
content_length = body.size
|
|
197
176
|
close_body = true
|
|
@@ -199,7 +178,7 @@ module Puma
|
|
|
199
178
|
body = res_body
|
|
200
179
|
end
|
|
201
180
|
elsif !res_body.is_a?(::File) && res_body.respond_to?(:to_path) &&
|
|
202
|
-
File.readable?(fn = res_body.to_path)
|
|
181
|
+
(fn = res_body.to_path) && File.readable?(fn = res_body.to_path)
|
|
203
182
|
body = File.open fn, 'rb'
|
|
204
183
|
content_length = body.size
|
|
205
184
|
close_body = true
|
|
@@ -237,8 +216,9 @@ module Puma
|
|
|
237
216
|
|
|
238
217
|
io_buffer << LINE_END
|
|
239
218
|
fast_write_str socket, io_buffer.read_and_reset
|
|
240
|
-
|
|
241
|
-
|
|
219
|
+
|
|
220
|
+
uncork_socket socket.flush
|
|
221
|
+
return keep_alive ? :keep_alive : :close
|
|
242
222
|
end
|
|
243
223
|
else
|
|
244
224
|
if content_length
|
|
@@ -256,25 +236,16 @@ module Puma
|
|
|
256
236
|
# response_hijack.call
|
|
257
237
|
if response_hijack
|
|
258
238
|
fast_write_str socket, io_buffer.read_and_reset
|
|
259
|
-
uncork_socket socket
|
|
239
|
+
uncork_socket socket.flush
|
|
260
240
|
response_hijack.call socket
|
|
261
241
|
return :async
|
|
262
242
|
end
|
|
263
243
|
|
|
264
244
|
fast_write_response socket, body, io_buffer, chunked, content_length.to_i
|
|
265
245
|
body.close if close_body
|
|
266
|
-
keep_alive
|
|
267
|
-
end
|
|
268
246
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
#
|
|
272
|
-
def default_server_port(env)
|
|
273
|
-
if ['on', HTTPS].include?(env[HTTPS_KEY]) || env[HTTP_X_FORWARDED_PROTO].to_s[0...5] == HTTPS || env[HTTP_X_FORWARDED_SCHEME] == HTTPS || env[HTTP_X_FORWARDED_SSL] == "on"
|
|
274
|
-
PORT_443
|
|
275
|
-
else
|
|
276
|
-
PORT_80
|
|
277
|
-
end
|
|
247
|
+
# if we're shutting down, close keep_alive connections
|
|
248
|
+
!shutting_down? && keep_alive ? :keep_alive : :close
|
|
278
249
|
end
|
|
279
250
|
|
|
280
251
|
# Used to write 'early hints', 'no body' responses, 'hijacked' responses,
|
|
@@ -391,6 +362,7 @@ module Puma
|
|
|
391
362
|
end
|
|
392
363
|
end
|
|
393
364
|
socket.flush
|
|
365
|
+
uncork_socket socket
|
|
394
366
|
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
|
395
367
|
raise ConnectionError, SOCKET_WRITE_ERR_MSG
|
|
396
368
|
rescue Errno::EPIPE, SystemCallError, IOError
|
|
@@ -399,85 +371,6 @@ module Puma
|
|
|
399
371
|
|
|
400
372
|
private :fast_write_str, :fast_write_response
|
|
401
373
|
|
|
402
|
-
# Given a Hash +env+ for the request read from +client+, add
|
|
403
|
-
# and fixup keys to comply with Rack's env guidelines.
|
|
404
|
-
# @param env [Hash] see Puma::Client#env, from request
|
|
405
|
-
# @param client [Puma::Client] only needed for Client#peerip
|
|
406
|
-
#
|
|
407
|
-
def normalize_env(env, client)
|
|
408
|
-
if host = env[HTTP_HOST]
|
|
409
|
-
# host can be a hostname, ipv4 or bracketed ipv6. Followed by an optional port.
|
|
410
|
-
if colon = host.rindex("]:") # IPV6 with port
|
|
411
|
-
env[SERVER_NAME] = host[0, colon+1]
|
|
412
|
-
env[SERVER_PORT] = host[colon+2, host.bytesize]
|
|
413
|
-
elsif !host.start_with?("[") && colon = host.index(":") # not hostname or IPV4 with port
|
|
414
|
-
env[SERVER_NAME] = host[0, colon]
|
|
415
|
-
env[SERVER_PORT] = host[colon+1, host.bytesize]
|
|
416
|
-
else
|
|
417
|
-
env[SERVER_NAME] = host
|
|
418
|
-
env[SERVER_PORT] = default_server_port(env)
|
|
419
|
-
end
|
|
420
|
-
else
|
|
421
|
-
env[SERVER_NAME] = LOCALHOST
|
|
422
|
-
env[SERVER_PORT] = default_server_port(env)
|
|
423
|
-
end
|
|
424
|
-
|
|
425
|
-
unless env[REQUEST_PATH]
|
|
426
|
-
# it might be a dumbass full host request header
|
|
427
|
-
uri = begin
|
|
428
|
-
URI.parse(env[REQUEST_URI])
|
|
429
|
-
rescue URI::InvalidURIError
|
|
430
|
-
raise Puma::HttpParserError
|
|
431
|
-
end
|
|
432
|
-
env[REQUEST_PATH] = uri.path
|
|
433
|
-
|
|
434
|
-
# A nil env value will cause a LintError (and fatal errors elsewhere),
|
|
435
|
-
# so only set the env value if there actually is a value.
|
|
436
|
-
env[QUERY_STRING] = uri.query if uri.query
|
|
437
|
-
end
|
|
438
|
-
|
|
439
|
-
env[PATH_INFO] = env[REQUEST_PATH].to_s # #to_s in case it's nil
|
|
440
|
-
|
|
441
|
-
# From https://www.ietf.org/rfc/rfc3875 :
|
|
442
|
-
# "Script authors should be aware that the REMOTE_ADDR and
|
|
443
|
-
# REMOTE_HOST meta-variables (see sections 4.1.8 and 4.1.9)
|
|
444
|
-
# may not identify the ultimate source of the request.
|
|
445
|
-
# They identify the client for the immediate request to the
|
|
446
|
-
# server; that client may be a proxy, gateway, or other
|
|
447
|
-
# intermediary acting on behalf of the actual source client."
|
|
448
|
-
#
|
|
449
|
-
|
|
450
|
-
unless env.key?(REMOTE_ADDR)
|
|
451
|
-
begin
|
|
452
|
-
addr = client.peerip
|
|
453
|
-
rescue Errno::ENOTCONN
|
|
454
|
-
# Client disconnects can result in an inability to get the
|
|
455
|
-
# peeraddr from the socket; default to unspec.
|
|
456
|
-
if client.peer_family == Socket::AF_INET6
|
|
457
|
-
addr = UNSPECIFIED_IPV6
|
|
458
|
-
else
|
|
459
|
-
addr = UNSPECIFIED_IPV4
|
|
460
|
-
end
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
# Set unix socket addrs to localhost
|
|
464
|
-
if addr.empty?
|
|
465
|
-
if client.peer_family == Socket::AF_INET6
|
|
466
|
-
addr = LOCALHOST_IPV6
|
|
467
|
-
else
|
|
468
|
-
addr = LOCALHOST_IPV4
|
|
469
|
-
end
|
|
470
|
-
end
|
|
471
|
-
|
|
472
|
-
env[REMOTE_ADDR] = addr
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
# The legacy HTTP_VERSION header can be sent as a client header.
|
|
476
|
-
# Rack v4 may remove using HTTP_VERSION. If so, remove this line.
|
|
477
|
-
env[HTTP_VERSION] = env[SERVER_PROTOCOL]
|
|
478
|
-
end
|
|
479
|
-
private :normalize_env
|
|
480
|
-
|
|
481
374
|
# @param header_key [#to_s]
|
|
482
375
|
# @return [Boolean]
|
|
483
376
|
#
|
|
@@ -491,56 +384,6 @@ module Puma
|
|
|
491
384
|
def illegal_header_value?(header_value)
|
|
492
385
|
!!(ILLEGAL_HEADER_VALUE_REGEX =~ header_value.to_s)
|
|
493
386
|
end
|
|
494
|
-
private :illegal_header_key?, :illegal_header_value?
|
|
495
|
-
|
|
496
|
-
# Fixup any headers with `,` in the name to have `_` now. We emit
|
|
497
|
-
# headers with `,` in them during the parse phase to avoid ambiguity
|
|
498
|
-
# with the `-` to `_` conversion for critical headers. But here for
|
|
499
|
-
# compatibility, we'll convert them back. This code is written to
|
|
500
|
-
# avoid allocation in the common case (ie there are no headers
|
|
501
|
-
# with `,` in their names), that's why it has the extra conditionals.
|
|
502
|
-
#
|
|
503
|
-
# @note If a normalized version of a `,` header already exists, we ignore
|
|
504
|
-
# the `,` version. This prevents clobbering headers managed by proxies
|
|
505
|
-
# but not by clients (Like X-Forwarded-For).
|
|
506
|
-
#
|
|
507
|
-
# @param env [Hash] see Puma::Client#env, from request, modifies in place
|
|
508
|
-
# @version 5.0.3
|
|
509
|
-
#
|
|
510
|
-
def req_env_post_parse(env)
|
|
511
|
-
to_delete = nil
|
|
512
|
-
to_add = nil
|
|
513
|
-
|
|
514
|
-
env.each do |k,v|
|
|
515
|
-
if k.start_with?("HTTP_") && k.include?(",") && !UNMASKABLE_HEADERS.key?(k)
|
|
516
|
-
if to_delete
|
|
517
|
-
to_delete << k
|
|
518
|
-
else
|
|
519
|
-
to_delete = [k]
|
|
520
|
-
end
|
|
521
|
-
|
|
522
|
-
new_k = k.tr(",", "_")
|
|
523
|
-
if env.key?(new_k)
|
|
524
|
-
next
|
|
525
|
-
end
|
|
526
|
-
|
|
527
|
-
unless to_add
|
|
528
|
-
to_add = {}
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
to_add[new_k] = v
|
|
532
|
-
end
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
if to_delete # rubocop:disable Style/SafeNavigation
|
|
536
|
-
to_delete.each { |k| env.delete(k) }
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
if to_add
|
|
540
|
-
env.merge! to_add
|
|
541
|
-
end
|
|
542
|
-
end
|
|
543
|
-
private :req_env_post_parse
|
|
544
387
|
|
|
545
388
|
# Used in the lambda for env[ `Puma::Const::EARLY_HINTS` ]
|
|
546
389
|
# @param headers [Hash] the headers returned by the Rack application
|
|
@@ -581,7 +424,7 @@ module Puma
|
|
|
581
424
|
# response body
|
|
582
425
|
# @param io_buffer [Puma::IOBuffer] modified inn place
|
|
583
426
|
# @param force_keep_alive [Boolean] 'anded' with keep_alive, based on system
|
|
584
|
-
# status and `@
|
|
427
|
+
# status and `@max_keep_alive`
|
|
585
428
|
# @return [Hash] resp_info
|
|
586
429
|
# @version 5.0.3
|
|
587
430
|
#
|
|
@@ -637,7 +480,8 @@ module Puma
|
|
|
637
480
|
headers.each do |k, vs|
|
|
638
481
|
next if illegal_header_key?(k)
|
|
639
482
|
|
|
640
|
-
|
|
483
|
+
key = k.downcase
|
|
484
|
+
case key
|
|
641
485
|
when CONTENT_LENGTH2
|
|
642
486
|
next if illegal_header_value?(vs)
|
|
643
487
|
# nil.to_i is 0, nil&.to_i is nil
|
|
@@ -664,10 +508,10 @@ module Puma
|
|
|
664
508
|
if ary
|
|
665
509
|
ary.each do |v|
|
|
666
510
|
next if illegal_header_value?(v)
|
|
667
|
-
io_buffer.append
|
|
511
|
+
io_buffer.append key, colon, v, line_ending
|
|
668
512
|
end
|
|
669
513
|
else
|
|
670
|
-
io_buffer.append
|
|
514
|
+
io_buffer.append key, colon, line_ending
|
|
671
515
|
end
|
|
672
516
|
end
|
|
673
517
|
|
data/lib/puma/runner.rb
CHANGED
|
@@ -33,7 +33,6 @@ module Puma
|
|
|
33
33
|
@wakeup.write PIPE_WAKEUP unless @wakeup.closed?
|
|
34
34
|
|
|
35
35
|
rescue SystemCallError, IOError
|
|
36
|
-
Puma::Util.purge_interrupt_queue
|
|
37
36
|
end
|
|
38
37
|
|
|
39
38
|
def development?
|
|
@@ -71,7 +70,7 @@ module Puma
|
|
|
71
70
|
token = nil if token.empty? || token == 'none'
|
|
72
71
|
end
|
|
73
72
|
|
|
74
|
-
app = Puma::App::Status.new @launcher, token
|
|
73
|
+
app = Puma::App::Status.new @launcher, token: token, data_only: @options[:control_data_only]
|
|
75
74
|
|
|
76
75
|
# A Reactor is not created and nio4r is not loaded when 'queue_requests: false'
|
|
77
76
|
# Use `nil` for events, no hooks in control server
|
|
@@ -93,22 +92,6 @@ module Puma
|
|
|
93
92
|
@control.binder.close_listeners if @control
|
|
94
93
|
end
|
|
95
94
|
|
|
96
|
-
# @!attribute [r] ruby_engine
|
|
97
|
-
# @deprecated Use `RUBY_DESCRIPTION` instead
|
|
98
|
-
def ruby_engine
|
|
99
|
-
warn "Puma::Runner#ruby_engine is deprecated; use RUBY_DESCRIPTION instead. It will be removed in puma v7."
|
|
100
|
-
|
|
101
|
-
if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
|
|
102
|
-
"ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
|
|
103
|
-
else
|
|
104
|
-
if defined?(RUBY_ENGINE_VERSION)
|
|
105
|
-
"#{RUBY_ENGINE} #{RUBY_ENGINE_VERSION} - ruby #{RUBY_VERSION}"
|
|
106
|
-
else
|
|
107
|
-
"#{RUBY_ENGINE} #{RUBY_VERSION}"
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
95
|
def output_header(mode)
|
|
113
96
|
min_t = @options[:min_threads]
|
|
114
97
|
max_t = @options[:max_threads]
|
|
@@ -128,6 +111,14 @@ module Puma
|
|
|
128
111
|
end
|
|
129
112
|
end
|
|
130
113
|
|
|
114
|
+
def warn_ruby_mn_threads
|
|
115
|
+
return if !ENV.key?('RUBY_MN_THREADS')
|
|
116
|
+
|
|
117
|
+
log "! WARNING: Detected `RUBY_MN_THREADS=#{ENV['RUBY_MN_THREADS']}`"
|
|
118
|
+
log "! This setting is known to cause performance regressions with Puma."
|
|
119
|
+
log "! Consider disabling this environment variable: https://github.com/puma/puma/issues/3720"
|
|
120
|
+
end
|
|
121
|
+
|
|
131
122
|
def redirected_io?
|
|
132
123
|
@options[:redirect_stdout] || @options[:redirect_stderr]
|
|
133
124
|
end
|