puma 6.0.2 → 6.2.2
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 +75 -0
- data/README.md +16 -4
- data/docs/systemd.md +1 -2
- data/lib/puma/binder.rb +4 -3
- data/lib/puma/cli.rb +1 -1
- data/lib/puma/client.rb +29 -4
- data/lib/puma/cluster/worker.rb +5 -0
- data/lib/puma/cluster.rb +2 -0
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +2 -0
- data/lib/puma/const.rb +2 -2
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +59 -2
- data/lib/puma/error_logger.rb +2 -1
- data/lib/puma/launcher.rb +9 -22
- data/lib/puma/log_writer.rb +13 -3
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/rack_default.rb +18 -3
- data/lib/puma/request.rb +79 -58
- data/lib/puma/runner.rb +7 -0
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +2 -0
- data/lib/puma/single.rb +2 -0
- data/lib/rack/handler/puma.rb +117 -94
- metadata +4 -3
- data/lib/puma/systemd.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5bf04e3d05e490359fd54acb971ea4316fbf6b51eec1c4d572359dd985eea92
|
4
|
+
data.tar.gz: a85be9bb75fd16c13600f918fedad71cdd9950293af84464d488ad5adbdc7cbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db99880324d78555ff6de88b5fd9eb37b5e169b2109c7021ca2a0f6325ce704f56d6ea2155099e7cee2bc71a8db73bf9fd12b97142c461c9e20ecbf4e7821463
|
7
|
+
data.tar.gz: 210d6a0a0cdd3922a792fd5311a4ae95ea6f3f1b04d5bd74daf316a55259f2c0f890b156d17812266ebf31a1a42ac860085f25bf5262a8556d987e4f5d3bc0f1
|
data/History.md
CHANGED
@@ -1,3 +1,50 @@
|
|
1
|
+
## 6.2.2 / 2023-04-17
|
2
|
+
|
3
|
+
* Bugfixes
|
4
|
+
* Fix Rack-related NameError by adding :: operator ([#3118], [#3117])
|
5
|
+
|
6
|
+
## 6.2.1 / 2023-03-31
|
7
|
+
|
8
|
+
* Bugfixes
|
9
|
+
* Fix java 8 compatibility ([#3109], [#3108])
|
10
|
+
* Always write io_buffer when in "enum bodies" branch. ([#3113], [#3112])
|
11
|
+
* Fix warn_if_in_single_mode incorrect message ([#3111])
|
12
|
+
|
13
|
+
## 6.2.0 / 2023-03-29
|
14
|
+
|
15
|
+
* Features
|
16
|
+
* Ability to supply a custom logger ([#2770], [#2511])
|
17
|
+
* Warn when clustered-only hooks are defined in single mode ([#3089])
|
18
|
+
* Adds the on_booted event ([#2709])
|
19
|
+
|
20
|
+
* Bugfixes
|
21
|
+
* Loggers - internal_write - catch Errno::EINVAL ([#3091])
|
22
|
+
* commonlogger.rb - fix HIJACK time format, use constants, not strings ([#3074])
|
23
|
+
* Fixed some edge cases regarding request hijacking ([#3072])
|
24
|
+
|
25
|
+
|
26
|
+
## 6.1.1 / 2023-02-28
|
27
|
+
|
28
|
+
* Bugfixes
|
29
|
+
* We no longer try to use the systemd plugin for JRuby ([#3079])
|
30
|
+
* Allow ::Rack::Handler::Puma.run to work regardless of whether Rack/Rackup are loaded ([#3080])
|
31
|
+
|
32
|
+
## 6.1.0 / 2023-02-12
|
33
|
+
|
34
|
+
* Features
|
35
|
+
* WebSocket support via partial hijack ([#3058], [#3007])
|
36
|
+
* Add built-in systemd notify support ([#3011])
|
37
|
+
* Periodically send status to systemd ([#3006], [#2604])
|
38
|
+
* Introduce the ability to return 413: payload too large for requests ([#3040])
|
39
|
+
* Log loaded extensions when `PUMA_DEBUG` is set ([#3036], [#3020])
|
40
|
+
|
41
|
+
* Bugfixes
|
42
|
+
* Fix issue with rack 3 compatibility re: rackup ([#3061], [#3057])
|
43
|
+
* Allow setting TCP low_latency with SSL listener ([#3065])
|
44
|
+
|
45
|
+
* Performance
|
46
|
+
* Reduce memory usage for large file uploads ([#3062])
|
47
|
+
|
1
48
|
## 6.0.2 / 2023-01-01
|
2
49
|
|
3
50
|
* Refactor
|
@@ -1932,6 +1979,34 @@ be added back in a future date when a java Puma::MiniSSL is added.
|
|
1932
1979
|
* Bugfixes
|
1933
1980
|
* Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
|
1934
1981
|
|
1982
|
+
[#3118]:https://github.com/puma/puma/pull/3118 "PR by @ninoseki, merged 2023-04-01"
|
1983
|
+
[#3117]:https://github.com/puma/puma/issues/3117 "Issue by @ninoseki, closed 2023-04-01"
|
1984
|
+
[#3109]:https://github.com/puma/puma/pull/3109 "PR by @ahorek, merged 2023-03-31"
|
1985
|
+
[#3108]:https://github.com/puma/puma/issues/3108 "Issue by @treviateo, closed 2023-03-31"
|
1986
|
+
[#3113]:https://github.com/puma/puma/pull/3113 "PR by @collinsauve, merged 2023-03-31"
|
1987
|
+
[#3112]:https://github.com/puma/puma/issues/3112 "Issue by @dmke, closed 2023-03-31"
|
1988
|
+
[#3111]:https://github.com/puma/puma/pull/3111 "PR by @adzap, merged 2023-03-30"
|
1989
|
+
[#2770]:https://github.com/puma/puma/pull/2770 "PR by @vzajkov, merged 2023-03-29"
|
1990
|
+
[#2511]:https://github.com/puma/puma/issues/2511 "Issue by @jchristie55332, closed 2021-12-12"
|
1991
|
+
[#3089]:https://github.com/puma/puma/pull/3089 "PR by @Vuta, merged 2023-03-06"
|
1992
|
+
[#2709]:https://github.com/puma/puma/pull/2709 "PR by @rodzyn, merged 2023-02-20"
|
1993
|
+
[#3091]:https://github.com/puma/puma/pull/3091 "PR by @MSP-Greg, merged 2023-03-28"
|
1994
|
+
[#3074]:https://github.com/puma/puma/pull/3074 "PR by @MSP-Greg, merged 2023-03-14"
|
1995
|
+
[#3072]:https://github.com/puma/puma/pull/3072 "PR by @MSP-Greg, merged 2023-02-17"
|
1996
|
+
[#3079]:https://github.com/puma/puma/pull/3079 "PR by @mohamedhafez, merged 2023-02-24"
|
1997
|
+
[#3080]:https://github.com/puma/puma/pull/3080 "PR by @MSP-Greg, merged 2023-02-16"
|
1998
|
+
[#3058]:https://github.com/puma/puma/pull/3058 "PR by @dentarg, merged 2023-01-29"
|
1999
|
+
[#3007]:https://github.com/puma/puma/issues/3007 "Issue by @MSP-Greg, closed 2023-01-29"
|
2000
|
+
[#3011]:https://github.com/puma/puma/pull/3011 "PR by @joaomarcos96, merged 2023-01-03"
|
2001
|
+
[#3006]:https://github.com/puma/puma/pull/3006 "PR by @QWYNG, merged 2023-02-09"
|
2002
|
+
[#2604]:https://github.com/puma/puma/issues/2604 "Issue by @dgoetz, closed 2023-02-09"
|
2003
|
+
[#3040]:https://github.com/puma/puma/pull/3040 "PR by @shayonj, merged 2023-01-02"
|
2004
|
+
[#3036]:https://github.com/puma/puma/pull/3036 "PR by @MSP-Greg, merged 2023-01-13"
|
2005
|
+
[#3020]:https://github.com/puma/puma/issues/3020 "Issue by @dentarg, closed 2023-01-13"
|
2006
|
+
[#3061]:https://github.com/puma/puma/pull/3061 "PR by @MSP-Greg, merged 2023-02-12"
|
2007
|
+
[#3057]:https://github.com/puma/puma/issues/3057 "Issue by @mmarvb8h, closed 2023-02-12"
|
2008
|
+
[#3065]:https://github.com/puma/puma/pull/3065 "PR by @MSP-Greg, merged 2023-02-11"
|
2009
|
+
[#3062]:https://github.com/puma/puma/pull/3062 "PR by @willkoehler, merged 2023-01-29"
|
1935
2010
|
[#3035]:https://github.com/puma/puma/pull/3035 "PR by @MSP-Greg, merged 2022-12-24"
|
1936
2011
|
[#3033]:https://github.com/puma/puma/issues/3033 "Issue by @jules-w2, closed 2022-12-24"
|
1937
2012
|
[#3016]:https://github.com/puma/puma/pull/3016 "PR by @MSP-Greg, merged 2022-12-24"
|
data/README.md
CHANGED
@@ -157,6 +157,15 @@ before_fork do
|
|
157
157
|
end
|
158
158
|
```
|
159
159
|
|
160
|
+
You can also specify a block to be run after puma is booted using `on_booted`:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
# config/puma.rb
|
164
|
+
on_booted do
|
165
|
+
# configuration here
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
160
169
|
### Error handling
|
161
170
|
|
162
171
|
If puma encounters an error outside of the context of your application, it will respond with a 500 and a simple
|
@@ -345,11 +354,13 @@ end
|
|
345
354
|
|
346
355
|
## Deployment
|
347
356
|
|
348
|
-
Puma has support for Capistrano with an [external gem](https://github.com/seuros/capistrano-puma).
|
357
|
+
* Puma has support for Capistrano with an [external gem](https://github.com/seuros/capistrano-puma).
|
358
|
+
|
359
|
+
* Additionally, Puma has support for built-in daemonization via the [puma-daemon](https://github.com/kigster/puma-daemon) ruby gem. The gem restores the `daemonize` option that was removed from Puma starting version 5, but only for MRI Ruby.
|
360
|
+
|
349
361
|
|
350
362
|
It is common to use process monitors with Puma. Modern process monitors like systemd or rc.d
|
351
|
-
provide continuous monitoring and restarts for increased
|
352
|
-
reliability in production environments:
|
363
|
+
provide continuous monitoring and restarts for increased reliability in production environments:
|
353
364
|
|
354
365
|
* [rc.d](docs/jungle/rc.d/README.md)
|
355
366
|
* [systemd](docs/systemd.md)
|
@@ -364,7 +375,8 @@ Community guides:
|
|
364
375
|
|
365
376
|
* [puma-metrics](https://github.com/harmjanblok/puma-metrics) — export Puma metrics to Prometheus
|
366
377
|
* [puma-plugin-statsd](https://github.com/yob/puma-plugin-statsd) — send Puma metrics to statsd
|
367
|
-
* [puma-plugin-systemd](https://github.com/sj26/puma-plugin-systemd) — deeper integration with systemd for notify, status and watchdog
|
378
|
+
* [puma-plugin-systemd](https://github.com/sj26/puma-plugin-systemd) — deeper integration with systemd for notify, status and watchdog. Puma 5.1.0 integrated notify and watchdog, which probably conflicts with this plugin. Puma 6.1.0 added status support which obsoletes the plugin entirely.
|
379
|
+
* [puma-plugin-telemetry](https://github.com/babbel/puma-plugin-telemetry) - telemetry plugin for Puma offering various targets to publish
|
368
380
|
|
369
381
|
### Monitoring
|
370
382
|
|
data/docs/systemd.md
CHANGED
@@ -24,8 +24,7 @@ After=network.target
|
|
24
24
|
|
25
25
|
[Service]
|
26
26
|
# Puma supports systemd's `Type=notify` and watchdog service
|
27
|
-
# monitoring,
|
28
|
-
# as of Puma 5.1 or later.
|
27
|
+
# monitoring, as of Puma 5.1 or later.
|
29
28
|
# On earlier versions of Puma or JRuby, change this to `Type=simple` and remove
|
30
29
|
# the `WatchdogSec` line.
|
31
30
|
Type=notify
|
data/lib/puma/binder.rb
CHANGED
@@ -158,10 +158,10 @@ module Puma
|
|
158
158
|
ios_len = @ios.length
|
159
159
|
params = Util.parse_query uri.query
|
160
160
|
|
161
|
-
|
161
|
+
low_latency = params.key?('low_latency') && params['low_latency'] != 'false'
|
162
162
|
backlog = params.fetch('backlog', 1024).to_i
|
163
163
|
|
164
|
-
io = add_tcp_listener uri.host, uri.port,
|
164
|
+
io = add_tcp_listener uri.host, uri.port, low_latency, backlog
|
165
165
|
|
166
166
|
@ios[ios_len..-1].each do |i|
|
167
167
|
addr = loc_addr_str i
|
@@ -251,7 +251,8 @@ module Puma
|
|
251
251
|
else
|
252
252
|
ios_len = @ios.length
|
253
253
|
backlog = params.fetch('backlog', 1024).to_i
|
254
|
-
|
254
|
+
low_latency = params['low_latency'] != 'false'
|
255
|
+
io = add_ssl_listener uri.host, uri.port, ctx, low_latency, backlog
|
255
256
|
|
256
257
|
@ios[ios_len..-1].each do |i|
|
257
258
|
addr = loc_addr_str i
|
data/lib/puma/cli.rb
CHANGED
@@ -93,7 +93,7 @@ module Puma
|
|
93
93
|
#
|
94
94
|
|
95
95
|
def setup_options
|
96
|
-
@conf = Configuration.new do |user_config, file_config|
|
96
|
+
@conf = Configuration.new({}, {events: @events}) do |user_config, file_config|
|
97
97
|
@parser = OptionParser.new do |o|
|
98
98
|
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
99
99
|
user_config.bind arg
|
data/lib/puma/client.rb
CHANGED
@@ -86,6 +86,9 @@ module Puma
|
|
86
86
|
@requests_served = 0
|
87
87
|
@hijacked = false
|
88
88
|
|
89
|
+
@http_content_length_limit = nil
|
90
|
+
@http_content_length_limit_exceeded = false
|
91
|
+
|
89
92
|
@peerip = nil
|
90
93
|
@peer_family = nil
|
91
94
|
@listener = nil
|
@@ -95,12 +98,14 @@ module Puma
|
|
95
98
|
@body_remain = 0
|
96
99
|
|
97
100
|
@in_last_chunk = false
|
101
|
+
|
102
|
+
@read_buffer = +""
|
98
103
|
end
|
99
104
|
|
100
105
|
attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked,
|
101
|
-
:tempfile, :io_buffer
|
106
|
+
:tempfile, :io_buffer, :http_content_length_limit_exceeded
|
102
107
|
|
103
|
-
attr_writer :peerip
|
108
|
+
attr_writer :peerip, :http_content_length_limit
|
104
109
|
|
105
110
|
attr_accessor :remote_addr_header, :listener
|
106
111
|
|
@@ -151,6 +156,7 @@ module Puma
|
|
151
156
|
@body_remain = 0
|
152
157
|
@peerip = nil if @remote_addr_header
|
153
158
|
@in_last_chunk = false
|
159
|
+
@http_content_length_limit_exceeded = false
|
154
160
|
|
155
161
|
if @buffer
|
156
162
|
return false unless try_to_parse_proxy_protocol
|
@@ -210,6 +216,17 @@ module Puma
|
|
210
216
|
end
|
211
217
|
|
212
218
|
def try_to_finish
|
219
|
+
if env[CONTENT_LENGTH] && above_http_content_limit(env[CONTENT_LENGTH].to_i)
|
220
|
+
@http_content_length_limit_exceeded = true
|
221
|
+
end
|
222
|
+
|
223
|
+
if @http_content_length_limit_exceeded
|
224
|
+
@buffer = nil
|
225
|
+
@body = EmptyBody
|
226
|
+
set_ready
|
227
|
+
return true
|
228
|
+
end
|
229
|
+
|
213
230
|
return read_body if in_data_phase
|
214
231
|
|
215
232
|
begin
|
@@ -239,6 +256,10 @@ module Puma
|
|
239
256
|
|
240
257
|
@parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)
|
241
258
|
|
259
|
+
if @parser.finished? && above_http_content_limit(@parser.body.bytesize)
|
260
|
+
@http_content_length_limit_exceeded = true
|
261
|
+
end
|
262
|
+
|
242
263
|
if @parser.finished?
|
243
264
|
return setup_body
|
244
265
|
elsif @parsed_bytes >= MAX_HEADER
|
@@ -414,7 +435,7 @@ module Puma
|
|
414
435
|
end
|
415
436
|
|
416
437
|
begin
|
417
|
-
chunk = @io.read_nonblock(want)
|
438
|
+
chunk = @io.read_nonblock(want, @read_buffer)
|
418
439
|
rescue IO::WaitReadable
|
419
440
|
return false
|
420
441
|
rescue SystemCallError, IOError
|
@@ -446,7 +467,7 @@ module Puma
|
|
446
467
|
def read_chunked_body
|
447
468
|
while true
|
448
469
|
begin
|
449
|
-
chunk = @io.read_nonblock(4096)
|
470
|
+
chunk = @io.read_nonblock(4096, @read_buffer)
|
450
471
|
rescue IO::WaitReadable
|
451
472
|
return false
|
452
473
|
rescue SystemCallError, IOError
|
@@ -594,5 +615,9 @@ module Puma
|
|
594
615
|
@requests_served += 1
|
595
616
|
@ready = true
|
596
617
|
end
|
618
|
+
|
619
|
+
def above_http_content_limit(value)
|
620
|
+
@http_content_length_limit&.< value
|
621
|
+
end
|
597
622
|
end
|
598
623
|
end
|
data/lib/puma/cluster/worker.rb
CHANGED
@@ -115,6 +115,11 @@ module Puma
|
|
115
115
|
|
116
116
|
while restart_server.pop
|
117
117
|
server_thread = server.run
|
118
|
+
|
119
|
+
if @log_writer.debug? && index == 0
|
120
|
+
debug_loaded_extensions "Loaded Extensions - worker 0:"
|
121
|
+
end
|
122
|
+
|
118
123
|
stat_thread ||= Thread.new(@worker_write) do |io|
|
119
124
|
Puma.set_thread_name "stat pld"
|
120
125
|
base_payload = "p#{Process.pid}"
|
data/lib/puma/cluster.rb
CHANGED
@@ -467,6 +467,7 @@ module Puma
|
|
467
467
|
@events.fire(:ping!, w)
|
468
468
|
if !booted && @workers.none? {|worker| worker.last_status.empty?}
|
469
469
|
@events.fire_on_booted!
|
470
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
470
471
|
booted = true
|
471
472
|
end
|
472
473
|
end
|
@@ -476,6 +477,7 @@ module Puma
|
|
476
477
|
end
|
477
478
|
if in_phased_restart && workers_not_booted.zero?
|
478
479
|
@events.fire_on_booted!
|
480
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
479
481
|
in_phased_restart = false
|
480
482
|
end
|
481
483
|
|
data/lib/puma/commonlogger.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Puma
|
4
4
|
# Rack::CommonLogger forwards every request to the given +app+, and
|
5
5
|
# logs a line in the
|
6
|
-
# {Apache common log format}[https://httpd.apache.org/docs/
|
6
|
+
# {Apache common log format}[https://httpd.apache.org/docs/2.4/logs.html#common]
|
7
7
|
# to the +logger+.
|
8
8
|
#
|
9
9
|
# If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
|
@@ -16,7 +16,7 @@ module Puma
|
|
16
16
|
# (which is called without arguments in order to make the error appear for
|
17
17
|
# sure)
|
18
18
|
class CommonLogger
|
19
|
-
# Common Log Format: https://httpd.apache.org/docs/
|
19
|
+
# Common Log Format: https://httpd.apache.org/docs/2.4/logs.html#common
|
20
20
|
#
|
21
21
|
# lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
|
22
22
|
#
|
@@ -25,10 +25,17 @@ module Puma
|
|
25
25
|
|
26
26
|
HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
LOG_TIME_FORMAT = '%d/%b/%Y:%H:%M:%S %z'
|
29
|
+
|
30
|
+
CONTENT_LENGTH = 'Content-Length' # should be lower case from app,
|
31
|
+
# Util::HeaderHash allows mixed
|
32
|
+
HTTP_VERSION = Const::HTTP_VERSION
|
33
|
+
HTTP_X_FORWARDED_FOR = Const::HTTP_X_FORWARDED_FOR
|
34
|
+
PATH_INFO = Const::PATH_INFO
|
35
|
+
QUERY_STRING = Const::QUERY_STRING
|
36
|
+
REMOTE_ADDR = Const::REMOTE_ADDR
|
37
|
+
REMOTE_USER = 'REMOTE_USER'
|
38
|
+
REQUEST_METHOD = Const::REQUEST_METHOD
|
32
39
|
|
33
40
|
def initialize(app, logger=nil)
|
34
41
|
@app = app
|
@@ -57,13 +64,13 @@ module Puma
|
|
57
64
|
now = Time.now
|
58
65
|
|
59
66
|
msg = HIJACK_FORMAT % [
|
60
|
-
env[
|
61
|
-
env[
|
62
|
-
now.strftime(
|
67
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
68
|
+
env[REMOTE_USER] || "-",
|
69
|
+
now.strftime(LOG_TIME_FORMAT),
|
63
70
|
env[REQUEST_METHOD],
|
64
71
|
env[PATH_INFO],
|
65
72
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
66
|
-
env[
|
73
|
+
env[HTTP_VERSION],
|
67
74
|
now - began_at ]
|
68
75
|
|
69
76
|
write(msg)
|
@@ -74,13 +81,13 @@ module Puma
|
|
74
81
|
length = extract_content_length(header)
|
75
82
|
|
76
83
|
msg = FORMAT % [
|
77
|
-
env[
|
78
|
-
env[
|
79
|
-
now.strftime(
|
84
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
85
|
+
env[REMOTE_USER] || "-",
|
86
|
+
now.strftime(LOG_TIME_FORMAT),
|
80
87
|
env[REQUEST_METHOD],
|
81
88
|
env[PATH_INFO],
|
82
89
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
83
|
-
env[
|
90
|
+
env[HTTP_VERSION],
|
84
91
|
status.to_s[0..3],
|
85
92
|
length,
|
86
93
|
now - began_at ]
|
data/lib/puma/configuration.rb
CHANGED
@@ -157,6 +157,7 @@ module Puma
|
|
157
157
|
reaping_time: 1,
|
158
158
|
remote_address: :socket,
|
159
159
|
silence_single_worker_warning: false,
|
160
|
+
silence_fork_callback_warning: false,
|
160
161
|
tag: File.basename(Dir.getwd),
|
161
162
|
tcp_host: '0.0.0.0'.freeze,
|
162
163
|
tcp_port: 9292,
|
@@ -167,6 +168,7 @@ module Puma
|
|
167
168
|
worker_shutdown_timeout: 30,
|
168
169
|
worker_timeout: 60,
|
169
170
|
workers: 0,
|
171
|
+
http_content_length_limit: nil
|
170
172
|
}
|
171
173
|
|
172
174
|
def initialize(user_options={}, default_options = {}, &block)
|
data/lib/puma/const.rb
CHANGED
@@ -99,8 +99,8 @@ module Puma
|
|
99
99
|
# too taxing on performance.
|
100
100
|
module Const
|
101
101
|
|
102
|
-
PUMA_VERSION = VERSION = "6.
|
103
|
-
CODE_NAME = "
|
102
|
+
PUMA_VERSION = VERSION = "6.2.2"
|
103
|
+
CODE_NAME = "Speaking of Now"
|
104
104
|
|
105
105
|
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
106
106
|
|
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)
|
@@ -114,7 +115,7 @@ module Puma
|
|
114
115
|
end
|
115
116
|
|
116
117
|
"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
|
+
"#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}#{low_latency_str}"
|
118
119
|
end
|
119
120
|
end
|
120
121
|
|
@@ -418,6 +419,11 @@ module Puma
|
|
418
419
|
@options[:log_requests] = which
|
419
420
|
end
|
420
421
|
|
422
|
+
# Pass in a custom logging class instance
|
423
|
+
def custom_logger(custom_logger)
|
424
|
+
@options[:custom_logger] = custom_logger
|
425
|
+
end
|
426
|
+
|
421
427
|
# Show debugging info
|
422
428
|
#
|
423
429
|
def debug
|
@@ -584,6 +590,11 @@ module Puma
|
|
584
590
|
@options[:silence_single_worker_warning] = true
|
585
591
|
end
|
586
592
|
|
593
|
+
# Disable warning message when running single mode with callback hook defined.
|
594
|
+
def silence_fork_callback_warning
|
595
|
+
@options[:silence_fork_callback_warning] = true
|
596
|
+
end
|
597
|
+
|
587
598
|
# Code to run immediately before master process
|
588
599
|
# forks workers (once on boot). These hooks can block if necessary
|
589
600
|
# to wait for background operations unknown to Puma to finish before
|
@@ -599,6 +610,8 @@ module Puma
|
|
599
610
|
# puts "Starting workers..."
|
600
611
|
# end
|
601
612
|
def before_fork(&block)
|
613
|
+
warn_if_in_single_mode('before_fork')
|
614
|
+
|
602
615
|
@options[:before_fork] ||= []
|
603
616
|
@options[:before_fork] << block
|
604
617
|
end
|
@@ -614,6 +627,8 @@ module Puma
|
|
614
627
|
# puts 'Before worker boot...'
|
615
628
|
# end
|
616
629
|
def on_worker_boot(key = nil, &block)
|
630
|
+
warn_if_in_single_mode('on_worker_boot')
|
631
|
+
|
617
632
|
process_hook :before_worker_boot, key, block, 'on_worker_boot'
|
618
633
|
end
|
619
634
|
|
@@ -630,6 +645,8 @@ module Puma
|
|
630
645
|
# puts 'On worker shutdown...'
|
631
646
|
# end
|
632
647
|
def on_worker_shutdown(key = nil, &block)
|
648
|
+
warn_if_in_single_mode('on_worker_shutdown')
|
649
|
+
|
633
650
|
process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
|
634
651
|
end
|
635
652
|
|
@@ -644,6 +661,8 @@ module Puma
|
|
644
661
|
# puts 'Before worker fork...'
|
645
662
|
# end
|
646
663
|
def on_worker_fork(&block)
|
664
|
+
warn_if_in_single_mode('on_worker_fork')
|
665
|
+
|
647
666
|
process_hook :before_worker_fork, nil, block, 'on_worker_fork'
|
648
667
|
end
|
649
668
|
|
@@ -658,11 +677,23 @@ module Puma
|
|
658
677
|
# puts 'After worker fork...'
|
659
678
|
# end
|
660
679
|
def after_worker_fork(&block)
|
680
|
+
warn_if_in_single_mode('after_worker_fork')
|
681
|
+
|
661
682
|
process_hook :after_worker_fork, nil, block, 'after_worker_fork'
|
662
683
|
end
|
663
684
|
|
664
685
|
alias_method :after_worker_boot, :after_worker_fork
|
665
686
|
|
687
|
+
# Code to run after puma is booted (works for both: single and clustered)
|
688
|
+
#
|
689
|
+
# @example
|
690
|
+
# on_booted do
|
691
|
+
# puts 'After booting...'
|
692
|
+
# end
|
693
|
+
def on_booted(&block)
|
694
|
+
@config.options[:events].on_booted(&block)
|
695
|
+
end
|
696
|
+
|
666
697
|
# When `fork_worker` is enabled, code to run in Worker 0
|
667
698
|
# before all other workers are re-forked from this process,
|
668
699
|
# after the server has temporarily stopped serving requests
|
@@ -1022,6 +1053,19 @@ module Puma
|
|
1022
1053
|
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
1023
1054
|
end
|
1024
1055
|
|
1056
|
+
# Specify how big the request payload should be, in bytes.
|
1057
|
+
# This limit is compared against Content-Length HTTP header.
|
1058
|
+
# If the payload size (CONTENT_LENGTH) is larger than http_content_length_limit,
|
1059
|
+
# HTTP 413 status code is returned.
|
1060
|
+
#
|
1061
|
+
# When no Content-Length http header is present, it is compared against the
|
1062
|
+
# size of the body of the request.
|
1063
|
+
#
|
1064
|
+
# The default value for http_content_length_limit is nil.
|
1065
|
+
def http_content_length_limit(limit)
|
1066
|
+
@options[:http_content_length_limit] = limit
|
1067
|
+
end
|
1068
|
+
|
1025
1069
|
private
|
1026
1070
|
|
1027
1071
|
# To avoid adding cert_pem and key_pem as URI params, we store them on the
|
@@ -1049,7 +1093,20 @@ module Puma
|
|
1049
1093
|
elsif key.nil?
|
1050
1094
|
@options[options_key] << block
|
1051
1095
|
else
|
1052
|
-
raise "'#{
|
1096
|
+
raise "'#{meth}' key must be String or Symbol"
|
1097
|
+
end
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
def warn_if_in_single_mode(hook_name)
|
1101
|
+
return if @options[:silence_fork_callback_warning]
|
1102
|
+
|
1103
|
+
if (@options[:workers] || 0) == 0
|
1104
|
+
log_string =
|
1105
|
+
"Warning: You specified code to run in a `#{hook_name}` block, " \
|
1106
|
+
"but Puma is not configured to run in cluster mode (worker count > 0 ), " \
|
1107
|
+
"so your `#{hook_name}` block did not run"
|
1108
|
+
|
1109
|
+
LogWriter.stdio.log(log_string)
|
1053
1110
|
end
|
1054
1111
|
end
|
1055
1112
|
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/launcher.rb
CHANGED
@@ -59,6 +59,13 @@ module Puma
|
|
59
59
|
|
60
60
|
@environment = conf.environment
|
61
61
|
|
62
|
+
# Load the systemd integration if we detect systemd's NOTIFY_SOCKET.
|
63
|
+
# Skip this on JRuby though, because it is incompatible with the systemd
|
64
|
+
# integration due to https://github.com/jruby/jruby/issues/6504
|
65
|
+
if ENV["NOTIFY_SOCKET"] && !Puma.jruby?
|
66
|
+
@config.plugins.create('systemd')
|
67
|
+
end
|
68
|
+
|
62
69
|
if @config.options[:bind_to_activated_sockets]
|
63
70
|
@config.options[:binds] = @binder.synthesize_binds_from_activated_fs(
|
64
71
|
@config.options[:binds],
|
@@ -72,6 +79,8 @@ module Puma
|
|
72
79
|
@log_writer.formatter = LogWriter::PidFormatter.new if clustered?
|
73
80
|
@log_writer.formatter = options[:log_formatter] if @options[:log_formatter]
|
74
81
|
|
82
|
+
@log_writer.custom_logger = options[:custom_logger] if @options[:custom_logger]
|
83
|
+
|
75
84
|
generate_restart_data
|
76
85
|
|
77
86
|
if clustered? && !Puma.forkable?
|
@@ -180,7 +189,6 @@ module Puma
|
|
180
189
|
|
181
190
|
setup_signals
|
182
191
|
set_process_title
|
183
|
-
integrate_with_systemd
|
184
192
|
|
185
193
|
# This blocks until the server is stopped
|
186
194
|
@runner.run
|
@@ -311,27 +319,6 @@ module Puma
|
|
311
319
|
@runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
|
312
320
|
end
|
313
321
|
|
314
|
-
# Puma's systemd integration allows Puma to inform systemd:
|
315
|
-
# 1. when it has successfully started
|
316
|
-
# 2. when it is starting shutdown
|
317
|
-
# 3. periodically for a liveness check with a watchdog thread
|
318
|
-
def integrate_with_systemd
|
319
|
-
return unless ENV["NOTIFY_SOCKET"]
|
320
|
-
|
321
|
-
begin
|
322
|
-
require_relative 'systemd'
|
323
|
-
rescue LoadError
|
324
|
-
log "Systemd integration failed. It looks like you're trying to use systemd notify but don't have sd_notify gem installed"
|
325
|
-
return
|
326
|
-
end
|
327
|
-
|
328
|
-
log "* Enabling systemd notification integration"
|
329
|
-
|
330
|
-
systemd = Systemd.new(@log_writer, @events)
|
331
|
-
systemd.hook_events
|
332
|
-
systemd.start_watchdog
|
333
|
-
end
|
334
|
-
|
335
322
|
def log(str)
|
336
323
|
@log_writer.log(str)
|
337
324
|
end
|
data/lib/puma/log_writer.rb
CHANGED
@@ -28,11 +28,12 @@ module Puma
|
|
28
28
|
attr_reader :stdout,
|
29
29
|
:stderr
|
30
30
|
|
31
|
-
attr_accessor :formatter
|
31
|
+
attr_accessor :formatter, :custom_logger
|
32
32
|
|
33
33
|
# Create a LogWriter that prints to +stdout+ and +stderr+.
|
34
34
|
def initialize(stdout, stderr)
|
35
35
|
@formatter = DefaultFormatter.new
|
36
|
+
@custom_logger = nil
|
36
37
|
@stdout = stdout
|
37
38
|
@stderr = stderr
|
38
39
|
|
@@ -59,7 +60,11 @@ module Puma
|
|
59
60
|
|
60
61
|
# Write +str+ to +@stdout+
|
61
62
|
def log(str)
|
62
|
-
|
63
|
+
if @custom_logger&.respond_to?(:write)
|
64
|
+
@custom_logger.write(format(str))
|
65
|
+
else
|
66
|
+
internal_write "#{@formatter.call str}\n"
|
67
|
+
end
|
63
68
|
end
|
64
69
|
|
65
70
|
def write(str)
|
@@ -73,13 +78,18 @@ module Puma
|
|
73
78
|
@stdout.is_a?(IO) and @stdout.wait_writable(1)
|
74
79
|
@stdout.write w_str
|
75
80
|
@stdout.flush unless @stdout.sync
|
76
|
-
rescue Errno::EPIPE, Errno::EBADF, IOError
|
81
|
+
rescue Errno::EPIPE, Errno::EBADF, IOError, Errno::EINVAL
|
82
|
+
# 'Invalid argument' (Errno::EINVAL) may be raised by flush
|
77
83
|
end
|
78
84
|
end
|
79
85
|
rescue ThreadError
|
80
86
|
end
|
81
87
|
private :internal_write
|
82
88
|
|
89
|
+
def debug?
|
90
|
+
@debug
|
91
|
+
end
|
92
|
+
|
83
93
|
def debug(str)
|
84
94
|
log("% #{str}") if @debug
|
85
95
|
end
|