puma 6.6.0 → 6.6.1
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 +20 -4
- data/README.md +8 -8
- data/docs/signals.md +2 -2
- data/docs/systemd.md +1 -1
- data/ext/puma_http11/org/jruby/puma/Http11.java +1 -1
- data/lib/puma/client.rb +43 -5
- data/lib/puma/cluster.rb +24 -10
- data/lib/puma/const.rb +1 -1
- data/lib/puma/dsl.rb +6 -13
- data/lib/puma/request.rb +12 -8
- data/lib/puma/single.rb +1 -1
- data/tools/Dockerfile +3 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 574e9afd59afd9a6d5b86bd74cc7e524e73982b61ca294884540cb54324771bf
|
4
|
+
data.tar.gz: 4702dc966028a0cb7c7f912ba6cdc33446071e8cd13ea63f14070f247f5d4504
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89dccb7f7cde9cc70904c28cf6026022239eac61fe8c903d924f10e50a59d17876d181feb4c80c7b4315c46d166fdcca7743dca16a3c52e27827f2e2d39a8ec3
|
7
|
+
data.tar.gz: c30aa7e48f3b6c191351ebe5c9b407fec7b2523c679bc915c21aefb854b0b43e7b9d776fcc3fdef574da70df71225ae4dbb78ed7045f4b178ae8a8578ae48efd
|
data/History.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 6.6.1 / 2025-07-30
|
2
|
+
|
3
|
+
* Bugfixes
|
4
|
+
* Accept `to_path` to be `nil` on request bodies ([#3635])
|
5
|
+
* Fix single runner stats before the server start ([#3572])
|
6
|
+
* Fix incomplete worker boot state on refork ([#3601])
|
7
|
+
* Improve HttpParserError messages for better debugging ([#3586])
|
8
|
+
* Fix refork logs to distinguish from phased restarts ([#3598])
|
9
|
+
* Fix `rack.after_reply` so it doesn't interrupt chain on error ([#3680])
|
10
|
+
|
1
11
|
## 6.6.0 / 2025-01-29
|
2
12
|
|
3
13
|
* Features
|
@@ -163,7 +173,7 @@
|
|
163
173
|
|
164
174
|
* Features
|
165
175
|
* Ability to supply a custom logger ([#2770], [#2511])
|
166
|
-
* Warn when
|
176
|
+
* Warn when cluster mode-only hooks are defined in single mode ([#3089])
|
167
177
|
* Adds the on_booted event ([#2709])
|
168
178
|
|
169
179
|
* Bugfixes
|
@@ -758,7 +768,7 @@ Each patchlevel release contains a separate security fix. We recommend simply up
|
|
758
768
|
* Fix Java 8 support ([#1773])
|
759
769
|
* Fix error `uninitialized constant Puma::Cluster` ([#1731])
|
760
770
|
* Fix `not_token` being able to be set to true ([#1803])
|
761
|
-
* Fix "Hang on SIGTERM with ruby 2.6 in
|
771
|
+
* Fix "Hang on SIGTERM with ruby 2.6 in cluster mode" (PR [#1741], [#1674], [#1720], [#1730], [#1755])
|
762
772
|
|
763
773
|
## 3.12.1 / 2019-03-19
|
764
774
|
|
@@ -1169,7 +1179,7 @@ Each patchlevel release contains a separate security fix. We recommend simply up
|
|
1169
1179
|
* 4 minor features:
|
1170
1180
|
|
1171
1181
|
* Listen to unix socket with provided backlog if any
|
1172
|
-
* Improves the
|
1182
|
+
* Improves the cluster mode stats to report worker stats
|
1173
1183
|
* Pass the env to the lowlevel_error handler. Fixes [#854]
|
1174
1184
|
* Treat path-like hosts as unix sockets. Fixes [#824]
|
1175
1185
|
|
@@ -1896,7 +1906,7 @@ The "clearly I don't have enough tests for the config" release.
|
|
1896
1906
|
|
1897
1907
|
* 3 doc changes:
|
1898
1908
|
* Add note about on_worker_boot hook
|
1899
|
-
* Add some documentation for
|
1909
|
+
* Add some documentation for Cluster mode
|
1900
1910
|
* Added quotes to /etc/puma.conf
|
1901
1911
|
|
1902
1912
|
## 2.0.1 / 2013-04-30
|
@@ -2150,6 +2160,12 @@ be added back in a future date when a java Puma::MiniSSL is added.
|
|
2150
2160
|
* Bugfixes
|
2151
2161
|
* Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
|
2152
2162
|
|
2163
|
+
[#3680]:https://github.com/puma/puma/pull/3680 "PR by @byroot, merged 2025-07-31"
|
2164
|
+
[#3572]:https://github.com/puma/puma/pull/3572 "PR by @barthez, merged 2025-02-06"
|
2165
|
+
[#3586]:https://github.com/puma/puma/pull/3586 "PR by @MSP-Greg, merged 2025-02-03"
|
2166
|
+
[#3598]:https://github.com/puma/puma/pull/3598 "PR by @joshuay03, merged 2025-01-31"
|
2167
|
+
[#3601]:https://github.com/puma/puma/pull/3601 "PR by @joshuay03, merged 2025-01-31"
|
2168
|
+
[#3635]:https://github.com/puma/puma/pull/3635 "PR by @LevitatingBusinessMan, merged 2025-05-08"
|
2153
2169
|
[#3570]:https://github.com/puma/puma/pull/3570 "PR by @mohamedhafez, merged 2024-12-30"
|
2154
2170
|
[#3567]:https://github.com/puma/puma/issues/3567 "Issue by @mohamedhafez, closed 2024-12-30"
|
2155
2171
|
[#3383]:https://github.com/puma/puma/pull/3383 "PR by @joshuay03, merged 2024-11-29"
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# Puma: A Ruby Web Server Built For Parallelism
|
6
6
|
|
7
|
-
[](https://github.com/puma/puma/actions/workflows/tests.yml?query=branch%3Amaster)
|
8
8
|
[](https://codeclimate.com/github/puma/puma)
|
9
9
|
[]( https://stackoverflow.com/questions/tagged/puma )
|
10
10
|
|
@@ -102,9 +102,9 @@ Puma will automatically scale the number of threads, from the minimum until it c
|
|
102
102
|
|
103
103
|
Be aware that additionally Puma creates threads on its own for internal purposes (e.g. handling slow clients). So, even if you specify -t 1:1, expect around 7 threads created in your application.
|
104
104
|
|
105
|
-
###
|
105
|
+
### Cluster mode
|
106
106
|
|
107
|
-
Puma also offers "
|
107
|
+
Puma also offers "cluster mode". Cluster mode `fork`s workers from a master process. Each child process still has its own thread pool. You can tune the number of workers with the `-w` (or `--workers`) flag:
|
108
108
|
|
109
109
|
```
|
110
110
|
$ puma -t 8:32 -w 3
|
@@ -116,13 +116,13 @@ Or with the `WEB_CONCURRENCY` environment variable:
|
|
116
116
|
$ WEB_CONCURRENCY=3 puma -t 8:32
|
117
117
|
```
|
118
118
|
|
119
|
-
Note that threads are still used in
|
119
|
+
Note that threads are still used in cluster mode, and the `-t` thread flag setting is per worker, so `-w 2 -t 16:16` will spawn 32 threads in total, with 16 in each worker process.
|
120
120
|
|
121
121
|
If the `WEB_CONCURRENCY` environment variable is set to `"auto"` and the `concurrent-ruby` gem is available in your application, Puma will set the worker process count to the result of [available processors](https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent.html#available_processor_count-class_method).
|
122
122
|
|
123
123
|
For an in-depth discussion of the tradeoffs of thread and process count settings, [see our docs](https://github.com/puma/puma/blob/9282a8efa5a0c48e39c60d22ca70051a25df9f55/docs/kubernetes.md#workers-per-pod-and-other-config-issues).
|
124
124
|
|
125
|
-
In
|
125
|
+
In cluster mode, Puma can "preload" your application. This loads all the application code *prior* to forking. Preloading reduces total memory usage of your application via an operating system feature called [copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write).
|
126
126
|
|
127
127
|
If the `WEB_CONCURRENCY` environment variable is set to a value > 1 (and `--prune-bundler` has not been specified), preloading will be enabled by default. Otherwise, you can use the `--preload` flag from the command line:
|
128
128
|
|
@@ -140,9 +140,9 @@ preload_app!
|
|
140
140
|
|
141
141
|
Preloading can’t be used with phased restart, since phased restart kills and restarts workers one-by-one, and preloading copies the code of master into the workers.
|
142
142
|
|
143
|
-
####
|
143
|
+
#### Cluster mode hooks
|
144
144
|
|
145
|
-
When using
|
145
|
+
When using cluster mode, Puma's configuration DSL provides `before_fork` and `on_worker_boot`
|
146
146
|
hooks to run code when the master process forks and child workers are booted respectively.
|
147
147
|
|
148
148
|
It is recommended to use these hooks with `preload_app!`, otherwise constants loaded by your
|
@@ -176,7 +176,7 @@ after_refork do
|
|
176
176
|
end
|
177
177
|
```
|
178
178
|
|
179
|
-
Importantly, note the following considerations when Ruby forks a child process:
|
179
|
+
Importantly, note the following considerations when Ruby forks a child process:
|
180
180
|
|
181
181
|
1. File descriptors such as network sockets **are** copied from the parent to the forked
|
182
182
|
child process. Dual-use of the same sockets by parent and child will result in I/O conflicts
|
data/docs/signals.md
CHANGED
@@ -17,13 +17,13 @@ $ ps aux | grep tail
|
|
17
17
|
schneems 87152 0.0 0.0 2432772 492 s032 S+ 12:46PM 0:00.00 tail -f my.log
|
18
18
|
```
|
19
19
|
|
20
|
-
You can send a signal in Ruby using the [Process module](https://ruby-
|
20
|
+
You can send a signal in Ruby using the [Process module](https://docs.ruby-lang.org/en/master/Process.html#method-c-kill):
|
21
21
|
|
22
22
|
```
|
23
23
|
$ irb
|
24
24
|
> puts pid
|
25
25
|
=> 87152
|
26
|
-
Process.detach(pid) # https://ruby-
|
26
|
+
Process.detach(pid) # https://docs.ruby-lang.org/en/master/Process.html#method-c-detach
|
27
27
|
Process.kill("TERM", pid)
|
28
28
|
```
|
29
29
|
|
data/docs/systemd.md
CHANGED
@@ -72,7 +72,7 @@ systemd and Puma also support socket activation, where systemd opens the
|
|
72
72
|
listening socket(s) in advance and provides them to the Puma master process on
|
73
73
|
startup. Among other advantages, this keeps listening sockets open across puma
|
74
74
|
restarts and achieves graceful restarts, including when upgraded Puma, and is
|
75
|
-
compatible with both
|
75
|
+
compatible with both cluster mode and application preload.
|
76
76
|
|
77
77
|
**Note:** Any wrapper scripts which `exec`, or other indirections in `ExecStart`
|
78
78
|
may result in activated socket file descriptors being closed before reaching the
|
@@ -29,7 +29,7 @@ public class Http11 extends RubyObject {
|
|
29
29
|
public final static int MAX_REQUEST_URI_LENGTH = getConstLength("PUMA_REQUEST_URI_MAX_LENGTH", 1024 * 12);
|
30
30
|
public final static String MAX_REQUEST_URI_LENGTH_ERR = "HTTP element REQUEST_URI is longer than the " + MAX_REQUEST_URI_LENGTH + " allowed length.";
|
31
31
|
public final static int MAX_FRAGMENT_LENGTH = 1024;
|
32
|
-
public final static String MAX_FRAGMENT_LENGTH_ERR = "HTTP element
|
32
|
+
public final static String MAX_FRAGMENT_LENGTH_ERR = "HTTP element FRAGMENT is longer than the 1024 allowed length.";
|
33
33
|
public final static int MAX_REQUEST_PATH_LENGTH = getConstLength("PUMA_REQUEST_PATH_MAX_LENGTH", 8192);
|
34
34
|
public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the " + MAX_REQUEST_PATH_LENGTH + " allowed length.";
|
35
35
|
public final static int MAX_QUERY_STRING_LENGTH = getConstLength("PUMA_QUERY_STRING_MAX_LENGTH", 10 * 1024);
|
data/lib/puma/client.rb
CHANGED
@@ -170,7 +170,7 @@ module Puma
|
|
170
170
|
if @buffer
|
171
171
|
return false unless try_to_parse_proxy_protocol
|
172
172
|
|
173
|
-
@parsed_bytes =
|
173
|
+
@parsed_bytes = parser_execute
|
174
174
|
|
175
175
|
if @parser.finished?
|
176
176
|
return setup_body
|
@@ -273,20 +273,20 @@ module Puma
|
|
273
273
|
|
274
274
|
return false unless try_to_parse_proxy_protocol
|
275
275
|
|
276
|
-
@parsed_bytes =
|
276
|
+
@parsed_bytes = parser_execute
|
277
277
|
|
278
278
|
if @parser.finished? && above_http_content_limit(@parser.body.bytesize)
|
279
279
|
@http_content_length_limit_exceeded = true
|
280
280
|
end
|
281
281
|
|
282
282
|
if @parser.finished?
|
283
|
-
|
283
|
+
setup_body
|
284
284
|
elsif @parsed_bytes >= MAX_HEADER
|
285
285
|
raise HttpParserError,
|
286
286
|
"HEADER is longer than allowed, aborting client early."
|
287
|
+
else
|
288
|
+
false
|
287
289
|
end
|
288
|
-
|
289
|
-
false
|
290
290
|
end
|
291
291
|
|
292
292
|
def eagerly_finish
|
@@ -300,6 +300,44 @@ module Puma
|
|
300
300
|
@to_io.wait_readable(timeout) || timeout! until try_to_finish
|
301
301
|
end
|
302
302
|
|
303
|
+
# Wraps `@parser.execute` and adds meaningful error messages
|
304
|
+
# @return [Integer] bytes of buffer read by parser
|
305
|
+
#
|
306
|
+
def parser_execute
|
307
|
+
@parser.execute(@env, @buffer, @parsed_bytes)
|
308
|
+
rescue => e
|
309
|
+
@env[HTTP_CONNECTION] = 'close'
|
310
|
+
raise e unless HttpParserError === e && e.message.include?('non-SSL')
|
311
|
+
|
312
|
+
req, _ = @buffer.split "\r\n\r\n"
|
313
|
+
request_line, headers = req.split "\r\n", 2
|
314
|
+
|
315
|
+
# below checks for request issues and changes error message accordingly
|
316
|
+
if !@env.key? REQUEST_METHOD
|
317
|
+
if request_line.count(' ') != 2
|
318
|
+
# maybe this is an SSL connection ?
|
319
|
+
raise e
|
320
|
+
else
|
321
|
+
method = request_line[/\A[^ ]+/]
|
322
|
+
raise e, "Invalid HTTP format, parsing fails. Bad method #{method}"
|
323
|
+
end
|
324
|
+
elsif !@env.key? REQUEST_PATH
|
325
|
+
path = request_line[/\A[^ ]+ +([^ ?\r\n]+)/, 1]
|
326
|
+
raise e, "Invalid HTTP format, parsing fails. Bad path #{path}"
|
327
|
+
elsif request_line.match?(/\A[^ ]+ +[^ ?\r\n]+\?/) && !@env.key?(QUERY_STRING)
|
328
|
+
query = request_line[/\A[^ ]+ +[^? ]+\?([^ ]+)/, 1]
|
329
|
+
raise e, "Invalid HTTP format, parsing fails. Bad query #{query}"
|
330
|
+
elsif !@env.key? SERVER_PROTOCOL
|
331
|
+
# protocol is bad
|
332
|
+
text = request_line[/[^ ]*\z/]
|
333
|
+
raise HttpParserError, "Invalid HTTP format, parsing fails. Bad protocol #{text}"
|
334
|
+
elsif !headers.empty?
|
335
|
+
# headers are bad
|
336
|
+
hdrs = headers.split("\r\n").map { |h| h.gsub "\n", '\n'}.join "\n"
|
337
|
+
raise HttpParserError, "Invalid HTTP format, parsing fails. Bad headers\n#{hdrs}"
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
303
341
|
def timeout!
|
304
342
|
write_error(408) if in_data_phase
|
305
343
|
raise ConnectionError
|
data/lib/puma/cluster.rb
CHANGED
@@ -44,10 +44,15 @@ module Puma
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
def start_phased_restart
|
47
|
+
def start_phased_restart(refork = false)
|
48
48
|
@events.fire_on_restart!
|
49
|
+
|
49
50
|
@phase += 1
|
50
|
-
|
51
|
+
if refork
|
52
|
+
log "- Starting worker refork, phase: #{@phase}"
|
53
|
+
else
|
54
|
+
log "- Starting phased worker restart, phase: #{@phase}"
|
55
|
+
end
|
51
56
|
|
52
57
|
# Be sure to change the directory again before loading
|
53
58
|
# the app. This way we can pick up new code.
|
@@ -166,7 +171,7 @@ module Puma
|
|
166
171
|
(@workers.map(&:pid) - idle_timed_out_worker_pids).empty?
|
167
172
|
end
|
168
173
|
|
169
|
-
def check_workers
|
174
|
+
def check_workers(refork = false)
|
170
175
|
return if @next_check >= Time.now
|
171
176
|
|
172
177
|
@next_check = Time.now + @options[:worker_check_interval]
|
@@ -184,7 +189,12 @@ module Puma
|
|
184
189
|
w = @workers.find { |x| x.phase != @phase }
|
185
190
|
|
186
191
|
if w
|
187
|
-
|
192
|
+
if refork
|
193
|
+
log "- Stopping #{w.pid} for refork..."
|
194
|
+
else
|
195
|
+
log "- Stopping #{w.pid} for phased upgrade..."
|
196
|
+
end
|
197
|
+
|
188
198
|
unless w.term?
|
189
199
|
w.term
|
190
200
|
log "- #{w.signal} sent to #{w.pid}..."
|
@@ -228,7 +238,7 @@ module Puma
|
|
228
238
|
def phased_restart(refork = false)
|
229
239
|
return false if @options[:preload_app] && !refork
|
230
240
|
|
231
|
-
@phased_restart = true
|
241
|
+
@phased_restart = refork ? :refork : true
|
232
242
|
wakeup!
|
233
243
|
|
234
244
|
true
|
@@ -368,7 +378,7 @@ module Puma
|
|
368
378
|
|
369
379
|
before = Thread.list.reject(&fork_safe)
|
370
380
|
|
371
|
-
log "* Restarts: (\u2714) hot (\u2716) phased"
|
381
|
+
log "* Restarts: (\u2714) hot (\u2716) phased (#{@options[:fork_worker] ? "\u2714" : "\u2716"}) refork"
|
372
382
|
log "* Preloading application"
|
373
383
|
load_and_bind
|
374
384
|
|
@@ -386,7 +396,7 @@ module Puma
|
|
386
396
|
end
|
387
397
|
end
|
388
398
|
else
|
389
|
-
log "* Restarts: (\u2714) hot (\u2714) phased"
|
399
|
+
log "* Restarts: (\u2714) hot (\u2714) phased (#{@options[:fork_worker] ? "\u2714" : "\u2716"}) refork"
|
390
400
|
|
391
401
|
unless @config.app_configured?
|
392
402
|
error "No application configured, nothing to run"
|
@@ -448,13 +458,17 @@ module Puma
|
|
448
458
|
end
|
449
459
|
|
450
460
|
if @phased_restart
|
451
|
-
start_phased_restart
|
461
|
+
start_phased_restart(@phased_restart == :refork)
|
462
|
+
|
463
|
+
in_phased_restart = @phased_restart
|
452
464
|
@phased_restart = false
|
453
|
-
|
465
|
+
|
454
466
|
workers_not_booted = @options[:workers]
|
467
|
+
# worker 0 is not restarted on refork
|
468
|
+
workers_not_booted -= 1 if in_phased_restart == :refork
|
455
469
|
end
|
456
470
|
|
457
|
-
check_workers
|
471
|
+
check_workers(in_phased_restart == :refork)
|
458
472
|
|
459
473
|
if read.wait_readable([0, @next_check - Time.now].max)
|
460
474
|
req = read.read_nonblock(1)
|
data/lib/puma/const.rb
CHANGED
@@ -100,7 +100,7 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "6.6.
|
103
|
+
PUMA_VERSION = VERSION = "6.6.1"
|
104
104
|
CODE_NAME = "Return to Forever"
|
105
105
|
|
106
106
|
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
data/lib/puma/dsl.rb
CHANGED
@@ -654,8 +654,6 @@ module Puma
|
|
654
654
|
# @example
|
655
655
|
# state_permission 0600
|
656
656
|
#
|
657
|
-
# @version 5.0.0
|
658
|
-
#
|
659
657
|
def state_permission(permission)
|
660
658
|
@options[:state_permission] = permission
|
661
659
|
end
|
@@ -811,7 +809,7 @@ module Puma
|
|
811
809
|
|
812
810
|
alias_method :after_worker_boot, :after_worker_fork
|
813
811
|
|
814
|
-
# Code to run after puma is booted (works for both
|
812
|
+
# Code to run after puma is booted (works for both single and cluster modes).
|
815
813
|
#
|
816
814
|
# @example
|
817
815
|
# on_booted do
|
@@ -822,7 +820,7 @@ module Puma
|
|
822
820
|
@config.options[:events].on_booted(&block)
|
823
821
|
end
|
824
822
|
|
825
|
-
# Code to run after puma is stopped (works for both
|
823
|
+
# Code to run after puma is stopped (works for both single and cluster modes).
|
826
824
|
#
|
827
825
|
# @example
|
828
826
|
# on_stopped do
|
@@ -851,8 +849,6 @@ module Puma
|
|
851
849
|
# 3.times {GC.start}
|
852
850
|
# end
|
853
851
|
#
|
854
|
-
# @version 5.0.0
|
855
|
-
#
|
856
852
|
def on_refork(key = nil, &block)
|
857
853
|
warn_if_in_single_mode('on_refork')
|
858
854
|
|
@@ -1111,7 +1107,7 @@ module Puma
|
|
1111
1107
|
|
1112
1108
|
# Set the timeout for worker shutdown.
|
1113
1109
|
#
|
1114
|
-
# The default is
|
1110
|
+
# The default is 30 seconds.
|
1115
1111
|
#
|
1116
1112
|
# @note Cluster mode only.
|
1117
1113
|
#
|
@@ -1143,10 +1139,10 @@ module Puma
|
|
1143
1139
|
# @see Puma::Cluster#cull_workers
|
1144
1140
|
#
|
1145
1141
|
def worker_culling_strategy(strategy)
|
1146
|
-
|
1142
|
+
strategy = strategy.to_sym
|
1147
1143
|
|
1148
1144
|
if ![:youngest, :oldest].include?(strategy)
|
1149
|
-
raise "Invalid value for worker_culling_strategy - #{
|
1145
|
+
raise "Invalid value for worker_culling_strategy - #{strategy}"
|
1150
1146
|
end
|
1151
1147
|
|
1152
1148
|
@options[:worker_culling_strategy] = strategy
|
@@ -1194,8 +1190,6 @@ module Puma
|
|
1194
1190
|
# @see Puma::Server#handle_servers
|
1195
1191
|
# @see Puma::ThreadPool#wait_for_less_busy_worker
|
1196
1192
|
#
|
1197
|
-
# @version 5.0.0
|
1198
|
-
#
|
1199
1193
|
def wait_for_less_busy_worker(val=0.005)
|
1200
1194
|
@options[:wait_for_less_busy_worker] = val.to_f
|
1201
1195
|
end
|
@@ -1269,10 +1263,9 @@ module Puma
|
|
1269
1263
|
# A refork will automatically trigger once after the specified number of requests
|
1270
1264
|
# (default 1000), or pass 0 to disable auto refork.
|
1271
1265
|
#
|
1266
|
+
# @note This is experimental.
|
1272
1267
|
# @note Cluster mode only.
|
1273
1268
|
#
|
1274
|
-
# @version 5.0.0
|
1275
|
-
#
|
1276
1269
|
def fork_worker(after_requests=1000)
|
1277
1270
|
@options[:fork_worker] = Integer(after_requests)
|
1278
1271
|
end
|
data/lib/puma/request.rb
CHANGED
@@ -135,12 +135,15 @@ module Puma
|
|
135
135
|
uncork_socket client.io
|
136
136
|
app_body.close if app_body.respond_to? :close
|
137
137
|
client&.tempfile_close
|
138
|
-
after_reply = env[RACK_AFTER_REPLY]
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
138
|
+
if after_reply = env[RACK_AFTER_REPLY]
|
139
|
+
after_reply.each do |o|
|
140
|
+
begin
|
141
|
+
o.call
|
142
|
+
rescue StandardError => e
|
143
|
+
@log_writer.debug_error e
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
144
147
|
end
|
145
148
|
|
146
149
|
# Assembles the headers and prepares the body for actually sending the
|
@@ -191,7 +194,8 @@ module Puma
|
|
191
194
|
elsif res_body.is_a?(File) && res_body.respond_to?(:size)
|
192
195
|
body = res_body
|
193
196
|
content_length = body.size
|
194
|
-
elsif res_body.respond_to?(:to_path) &&
|
197
|
+
elsif res_body.respond_to?(:to_path) && (fn = res_body.to_path) &&
|
198
|
+
File.readable?(fn)
|
195
199
|
body = File.open fn, 'rb'
|
196
200
|
content_length = body.size
|
197
201
|
close_body = true
|
@@ -199,7 +203,7 @@ module Puma
|
|
199
203
|
body = res_body
|
200
204
|
end
|
201
205
|
elsif !res_body.is_a?(::File) && res_body.respond_to?(:to_path) &&
|
202
|
-
File.readable?(fn = res_body.to_path)
|
206
|
+
(fn = res_body.to_path) && File.readable?(fn = res_body.to_path)
|
203
207
|
body = File.open fn, 'rb'
|
204
208
|
content_length = body.size
|
205
209
|
close_body = true
|
data/lib/puma/single.rb
CHANGED
data/tools/Dockerfile
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
FROM ruby:3.2
|
4
4
|
|
5
|
+
RUN apt-get update && apt-get install -y ragel
|
6
|
+
|
5
7
|
# throw errors if Gemfile has been modified since Gemfile.lock
|
6
8
|
RUN bundle config --global frozen 1
|
7
9
|
|
@@ -13,4 +15,4 @@ RUN bundle install
|
|
13
15
|
RUN bundle exec rake compile
|
14
16
|
|
15
17
|
EXPOSE 9292
|
16
|
-
CMD bundle exec bin/puma test/rackup/hello.ru
|
18
|
+
CMD ["bundle", "exec", "bin/puma", "test/rackup/hello.ru"]
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.6.
|
4
|
+
version: 6.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: nio4r
|
@@ -145,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '0'
|
147
147
|
requirements: []
|
148
|
-
rubygems_version: 3.6.
|
148
|
+
rubygems_version: 3.6.9
|
149
149
|
specification_version: 4
|
150
150
|
summary: A Ruby/Rack web server built for parallelism.
|
151
151
|
test_files: []
|