puma 6.0.0 → 6.1.1
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 +68 -5
- data/README.md +1 -0
- data/docs/nginx.md +1 -1
- data/docs/systemd.md +1 -2
- data/lib/puma/binder.rb +4 -3
- data/lib/puma/client.rb +32 -4
- data/lib/puma/cluster/worker.rb +5 -0
- data/lib/puma/cluster.rb +5 -5
- data/lib/puma/configuration.rb +1 -0
- data/lib/puma/const.rb +76 -84
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +18 -1
- data/lib/puma/io_buffer.rb +10 -0
- data/lib/puma/launcher.rb +7 -22
- data/lib/puma/log_writer.rb +4 -0
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/rack_default.rb +18 -3
- data/lib/puma/reactor.rb +1 -1
- data/lib/puma/request.rb +154 -106
- data/lib/puma/runner.rb +11 -0
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +6 -7
- data/lib/puma/single.rb +3 -1
- data/lib/puma/thread_pool.rb +1 -4
- data/lib/puma.rb +1 -3
- data/lib/rack/handler/puma.rb +115 -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: 6a987a441328b2f8be7f7a147af233c0c41b393b98714ed621e2508dc28819d8
|
4
|
+
data.tar.gz: bc30afa48b1647abf34f6cf362e3374b76a7e25c605f3ed7e5fd1e7c96dad8fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a1a05276e82ffd6d012bc75e6f38c2bf30932cb9cd9a6b73a14d783e012f4b942128a72bf0bb8f9bbf8a0062c03d5df234a6baccbc490a2bb64150f480b531f
|
7
|
+
data.tar.gz: 6127f2e9b3fd82795696ecd8e0f2016b7252f71d86433087c42c826c7d0d1cc8d2ceda8e4243bf99969d96ba261172e39d59e977ba24d5d75225d7707c64f2a9
|
data/History.md
CHANGED
@@ -1,4 +1,41 @@
|
|
1
|
-
## 6.
|
1
|
+
## 6.1.1 / 2023-02-28
|
2
|
+
|
3
|
+
* Bugfixes
|
4
|
+
* We no longer try to use the systemd plugin for JRuby ([#3079])
|
5
|
+
* Allow ::Rack::Handler::Puma.run to work regardless of whether Rack/Rackup are loaded ([#3080])
|
6
|
+
|
7
|
+
## 6.1.0 / 2023-02-12
|
8
|
+
|
9
|
+
* Features
|
10
|
+
* WebSocket support via partial hijack ([#3058], [#3007])
|
11
|
+
* Add built-in systemd notify support ([#3011])
|
12
|
+
* Periodically send status to systemd ([#3006], [#2604])
|
13
|
+
* Introduce the ability to return 413: payload too large for requests ([#3040])
|
14
|
+
* Log loaded extensions when `PUMA_DEBUG` is set ([#3036], [#3020])
|
15
|
+
|
16
|
+
* Bugfixes
|
17
|
+
* Fix issue with rack 3 compatibility re: rackup ([#3061], [#3057])
|
18
|
+
* Allow setting TCP low_latency with SSL listener ([#3065])
|
19
|
+
|
20
|
+
* Performance
|
21
|
+
* Reduce memory usage for large file uploads ([#3062])
|
22
|
+
|
23
|
+
## 6.0.2 / 2023-01-01
|
24
|
+
|
25
|
+
* Refactor
|
26
|
+
* Remove use of etc and time gems in Puma ([#3035], [#3033])
|
27
|
+
* Refactor const.rb - freeze ([#3016])
|
28
|
+
|
29
|
+
## 6.0.1 / 2022-12-20
|
30
|
+
|
31
|
+
* Bugfixes
|
32
|
+
* Handle waking up a closed selector in Reactor#add ([#3005])
|
33
|
+
* Fixup response processing, enumerable bodies ([#3004], [#3000])
|
34
|
+
* Correctly close app body for all code paths ([#3002], [#2999])
|
35
|
+
* Refactor
|
36
|
+
* Add IOBuffer to Client, remove from ThreadPool thread instances ([#3013])
|
37
|
+
|
38
|
+
## 6.0.0 / 2022-10-14
|
2
39
|
|
3
40
|
* Breaking Changes
|
4
41
|
* Dropping Ruby 2.2 and 2.3 support (now 2.4+) ([#2919])
|
@@ -9,6 +46,9 @@
|
|
9
46
|
* Prefix all environment variables with `PUMA_` ([#2924], [#2853])
|
10
47
|
* Removed some constants ([#2957], [#2958], [#2959], [#2960])
|
11
48
|
* The following classes are now part of Puma's private API: `Client`, `Cluster::Worker`, `Cluster::Worker`, `HandleRequest`. ([#2988])
|
49
|
+
* Configuration constants like `DefaultRackup` removed ([#2928])
|
50
|
+
* Extracted `LogWriter` from `Events` ([#2798])
|
51
|
+
* Only accept the standard 8 HTTP methods, others rejected with 501. ([#2932])
|
12
52
|
|
13
53
|
* Features
|
14
54
|
* Increase throughput on large (100kb+) response bodies by 3-10x ([#2896], [#2892])
|
@@ -34,7 +74,6 @@
|
|
34
74
|
|
35
75
|
* Refactor
|
36
76
|
* log_writer.rb - add internal_write method ([#2888])
|
37
|
-
* [WIP] Refactor: Split out LogWriter from Events (no logic change) ([#2798])
|
38
77
|
* Extract prune_bundler code into it's own class. ([#2797])
|
39
78
|
* Refactor Launcher#run to increase readability (no logic change) ([#2795])
|
40
79
|
* Ruby 3.2 will have native IO#wait_* methods, don't require io/wait ([#2903])
|
@@ -1915,6 +1954,29 @@ be added back in a future date when a java Puma::MiniSSL is added.
|
|
1915
1954
|
* Bugfixes
|
1916
1955
|
* Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
|
1917
1956
|
|
1957
|
+
[#3079]:https://github.com/puma/puma/pull/3079 "PR by @mohamedhafez, merged 2023-02-24"
|
1958
|
+
[#3080]:https://github.com/puma/puma/pull/3080 "PR by @MSP-Greg, merged 2023-02-16"
|
1959
|
+
[#3058]:https://github.com/puma/puma/pull/3058 "PR by @dentarg, merged 2023-01-29"
|
1960
|
+
[#3007]:https://github.com/puma/puma/issues/3007 "Issue by @MSP-Greg, closed 2023-01-29"
|
1961
|
+
[#3011]:https://github.com/puma/puma/pull/3011 "PR by @joaomarcos96, merged 2023-01-03"
|
1962
|
+
[#3006]:https://github.com/puma/puma/pull/3006 "PR by @QWYNG, merged 2023-02-09"
|
1963
|
+
[#2604]:https://github.com/puma/puma/issues/2604 "Issue by @dgoetz, closed 2023-02-09"
|
1964
|
+
[#3040]:https://github.com/puma/puma/pull/3040 "PR by @shayonj, merged 2023-01-02"
|
1965
|
+
[#3036]:https://github.com/puma/puma/pull/3036 "PR by @MSP-Greg, merged 2023-01-13"
|
1966
|
+
[#3020]:https://github.com/puma/puma/issues/3020 "Issue by @dentarg, closed 2023-01-13"
|
1967
|
+
[#3061]:https://github.com/puma/puma/pull/3061 "PR by @MSP-Greg, merged 2023-02-12"
|
1968
|
+
[#3057]:https://github.com/puma/puma/issues/3057 "Issue by @mmarvb8h, closed 2023-02-12"
|
1969
|
+
[#3065]:https://github.com/puma/puma/pull/3065 "PR by @MSP-Greg, merged 2023-02-11"
|
1970
|
+
[#3062]:https://github.com/puma/puma/pull/3062 "PR by @willkoehler, merged 2023-01-29"
|
1971
|
+
[#3035]:https://github.com/puma/puma/pull/3035 "PR by @MSP-Greg, merged 2022-12-24"
|
1972
|
+
[#3033]:https://github.com/puma/puma/issues/3033 "Issue by @jules-w2, closed 2022-12-24"
|
1973
|
+
[#3016]:https://github.com/puma/puma/pull/3016 "PR by @MSP-Greg, merged 2022-12-24"
|
1974
|
+
[#3005]:https://github.com/puma/puma/pull/3005 "PR by @JuanitoFatas, merged 2022-11-04"
|
1975
|
+
[#3004]:https://github.com/puma/puma/pull/3004 "PR by @MSP-Greg, merged 2022-11-24"
|
1976
|
+
[#3000]:https://github.com/puma/puma/issues/3000 "Issue by @dentarg, closed 2022-11-24"
|
1977
|
+
[#3002]:https://github.com/puma/puma/pull/3002 "PR by @MSP-Greg, merged 2022-11-03"
|
1978
|
+
[#2999]:https://github.com/puma/puma/issues/2999 "Issue by @aymeric-ledorze, closed 2022-11-03"
|
1979
|
+
[#3013]:https://github.com/puma/puma/pull/3013 "PR by @MSP-Greg, merged 2022-11-13"
|
1918
1980
|
[#2919]:https://github.com/puma/puma/pull/2919 "PR by @MSP-Greg, merged 2022-08-30"
|
1919
1981
|
[#2652]:https://github.com/puma/puma/issues/2652 "Issue by @Roguelazer, closed 2022-09-04"
|
1920
1982
|
[#2653]:https://github.com/puma/puma/pull/2653 "PR by @Roguelazer, closed 2022-03-07"
|
@@ -1928,7 +1990,10 @@ be added back in a future date when a java Puma::MiniSSL is added.
|
|
1928
1990
|
[#2958]:https://github.com/puma/puma/pull/2958 "PR by @JuanitoFatas, merged 2022-09-16"
|
1929
1991
|
[#2959]:https://github.com/puma/puma/pull/2959 "PR by @JuanitoFatas, merged 2022-09-16"
|
1930
1992
|
[#2960]:https://github.com/puma/puma/pull/2960 "PR by @JuanitoFatas, merged 2022-09-16"
|
1931
|
-
[#2988]:https://github.com/puma/puma/
|
1993
|
+
[#2988]:https://github.com/puma/puma/pull/2988 "PR by @MSP-Greg, merged 2022-10-12"
|
1994
|
+
[#2928]:https://github.com/puma/puma/pull/2928 "PR by @nateberkopec, merged 2022-09-10"
|
1995
|
+
[#2798]:https://github.com/puma/puma/pull/2798 "PR by @johnnyshields, merged 2022-02-05"
|
1996
|
+
[#2932]:https://github.com/puma/puma/pull/2932 "PR by @mrzasa, merged 2022-09-12"
|
1932
1997
|
[#2896]:https://github.com/puma/puma/pull/2896 "PR by @MSP-Greg, merged 2022-09-13"
|
1933
1998
|
[#2892]:https://github.com/puma/puma/pull/2892 "PR by @guilleiguaran, closed 2022-09-13"
|
1934
1999
|
[#2923]:https://github.com/puma/puma/pull/2923 "PR by @nateberkopec, merged 2022-09-09"
|
@@ -1949,11 +2014,9 @@ be added back in a future date when a java Puma::MiniSSL is added.
|
|
1949
2014
|
[#2904]:https://github.com/puma/puma/pull/2904 "PR by @kares, merged 2022-08-27"
|
1950
2015
|
[#2884]:https://github.com/puma/puma/pull/2884 "PR by @kares, merged 2022-05-30"
|
1951
2016
|
[#2897]:https://github.com/puma/puma/pull/2897 "PR by @Edouard-chin, merged 2022-08-27"
|
1952
|
-
[#2932]:https://github.com/puma/puma/pull/2932 "PR by @mrzasa, merged 2022-09-12"
|
1953
2017
|
[#1441]:https://github.com/puma/puma/issues/1441 "Issue by @nirvdrum, closed 2022-09-12"
|
1954
2018
|
[#2956]:https://github.com/puma/puma/pull/2956 "PR by @MSP-Greg, merged 2022-09-15"
|
1955
2019
|
[#2888]:https://github.com/puma/puma/pull/2888 "PR by @MSP-Greg, merged 2022-06-01"
|
1956
|
-
[#2798]:https://github.com/puma/puma/pull/2798 "PR by @johnnyshields, merged 2022-02-05"
|
1957
2020
|
[#2797]:https://github.com/puma/puma/pull/2797 "PR by @johnnyshields, merged 2022-02-01"
|
1958
2021
|
[#2795]:https://github.com/puma/puma/pull/2795 "PR by @johnnyshields, merged 2022-01-31"
|
1959
2022
|
[#2903]:https://github.com/puma/puma/pull/2903 "PR by @MSP-Greg, merged 2022-08-27"
|
data/README.md
CHANGED
@@ -365,6 +365,7 @@ Community guides:
|
|
365
365
|
* [puma-metrics](https://github.com/harmjanblok/puma-metrics) — export Puma metrics to Prometheus
|
366
366
|
* [puma-plugin-statsd](https://github.com/yob/puma-plugin-statsd) — send Puma metrics to statsd
|
367
367
|
* [puma-plugin-systemd](https://github.com/sj26/puma-plugin-systemd) — deeper integration with systemd for notify, status and watchdog
|
368
|
+
* [puma-plugin-telemetry](https://github.com/babbel/puma-plugin-telemetry) - telemetry plugin for Puma offering various targets to publish
|
368
369
|
|
369
370
|
### Monitoring
|
370
371
|
|
data/docs/nginx.md
CHANGED
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/client.rb
CHANGED
@@ -9,6 +9,7 @@ class IO
|
|
9
9
|
end
|
10
10
|
|
11
11
|
require_relative 'detect'
|
12
|
+
require_relative 'io_buffer'
|
12
13
|
require 'tempfile'
|
13
14
|
require 'forwardable'
|
14
15
|
|
@@ -65,6 +66,7 @@ module Puma
|
|
65
66
|
def initialize(io, env=nil)
|
66
67
|
@io = io
|
67
68
|
@to_io = io.to_io
|
69
|
+
@io_buffer = IOBuffer.new
|
68
70
|
@proto_env = env
|
69
71
|
@env = env ? env.dup : nil
|
70
72
|
|
@@ -84,6 +86,9 @@ module Puma
|
|
84
86
|
@requests_served = 0
|
85
87
|
@hijacked = false
|
86
88
|
|
89
|
+
@http_content_length_limit = nil
|
90
|
+
@http_content_length_limit_exceeded = false
|
91
|
+
|
87
92
|
@peerip = nil
|
88
93
|
@peer_family = nil
|
89
94
|
@listener = nil
|
@@ -93,12 +98,14 @@ module Puma
|
|
93
98
|
@body_remain = 0
|
94
99
|
|
95
100
|
@in_last_chunk = false
|
101
|
+
|
102
|
+
@read_buffer = +""
|
96
103
|
end
|
97
104
|
|
98
105
|
attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked,
|
99
|
-
:tempfile
|
106
|
+
:tempfile, :io_buffer, :http_content_length_limit_exceeded
|
100
107
|
|
101
|
-
attr_writer :peerip
|
108
|
+
attr_writer :peerip, :http_content_length_limit
|
102
109
|
|
103
110
|
attr_accessor :remote_addr_header, :listener
|
104
111
|
|
@@ -138,6 +145,7 @@ module Puma
|
|
138
145
|
|
139
146
|
def reset(fast_check=true)
|
140
147
|
@parser.reset
|
148
|
+
@io_buffer.reset
|
141
149
|
@read_header = true
|
142
150
|
@read_proxy = !!@expect_proxy_proto
|
143
151
|
@env = @proto_env.dup
|
@@ -148,6 +156,7 @@ module Puma
|
|
148
156
|
@body_remain = 0
|
149
157
|
@peerip = nil if @remote_addr_header
|
150
158
|
@in_last_chunk = false
|
159
|
+
@http_content_length_limit_exceeded = false
|
151
160
|
|
152
161
|
if @buffer
|
153
162
|
return false unless try_to_parse_proxy_protocol
|
@@ -207,6 +216,17 @@ module Puma
|
|
207
216
|
end
|
208
217
|
|
209
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
|
+
|
210
230
|
return read_body if in_data_phase
|
211
231
|
|
212
232
|
begin
|
@@ -236,6 +256,10 @@ module Puma
|
|
236
256
|
|
237
257
|
@parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)
|
238
258
|
|
259
|
+
if @parser.finished? && above_http_content_limit(@parser.body.bytesize)
|
260
|
+
@http_content_length_limit_exceeded = true
|
261
|
+
end
|
262
|
+
|
239
263
|
if @parser.finished?
|
240
264
|
return setup_body
|
241
265
|
elsif @parsed_bytes >= MAX_HEADER
|
@@ -411,7 +435,7 @@ module Puma
|
|
411
435
|
end
|
412
436
|
|
413
437
|
begin
|
414
|
-
chunk = @io.read_nonblock(want)
|
438
|
+
chunk = @io.read_nonblock(want, @read_buffer)
|
415
439
|
rescue IO::WaitReadable
|
416
440
|
return false
|
417
441
|
rescue SystemCallError, IOError
|
@@ -443,7 +467,7 @@ module Puma
|
|
443
467
|
def read_chunked_body
|
444
468
|
while true
|
445
469
|
begin
|
446
|
-
chunk = @io.read_nonblock(4096)
|
470
|
+
chunk = @io.read_nonblock(4096, @read_buffer)
|
447
471
|
rescue IO::WaitReadable
|
448
472
|
return false
|
449
473
|
rescue SystemCallError, IOError
|
@@ -591,5 +615,9 @@ module Puma
|
|
591
615
|
@requests_served += 1
|
592
616
|
@ready = true
|
593
617
|
end
|
618
|
+
|
619
|
+
def above_http_content_limit(value)
|
620
|
+
@http_content_length_limit&.< value
|
621
|
+
end
|
594
622
|
end
|
595
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
@@ -6,8 +6,6 @@ require_relative 'plugin'
|
|
6
6
|
require_relative 'cluster/worker_handle'
|
7
7
|
require_relative 'cluster/worker'
|
8
8
|
|
9
|
-
require 'time'
|
10
|
-
|
11
9
|
module Puma
|
12
10
|
# This class is instantiated by the `Puma::Launcher` and used
|
13
11
|
# to boot and serve a Ruby application when puma "workers" are needed
|
@@ -252,18 +250,18 @@ module Puma
|
|
252
250
|
old_worker_count = @workers.count { |w| w.phase != @phase }
|
253
251
|
worker_status = @workers.map do |w|
|
254
252
|
{
|
255
|
-
started_at: w.started_at
|
253
|
+
started_at: utc_iso8601(w.started_at),
|
256
254
|
pid: w.pid,
|
257
255
|
index: w.index,
|
258
256
|
phase: w.phase,
|
259
257
|
booted: w.booted?,
|
260
|
-
last_checkin: w.last_checkin
|
258
|
+
last_checkin: utc_iso8601(w.last_checkin),
|
261
259
|
last_status: w.last_status,
|
262
260
|
}
|
263
261
|
end
|
264
262
|
|
265
263
|
{
|
266
|
-
started_at: @started_at
|
264
|
+
started_at: utc_iso8601(@started_at),
|
267
265
|
workers: @workers.size,
|
268
266
|
phase: @phase,
|
269
267
|
booted_workers: worker_status.count { |w| w[:booted] },
|
@@ -469,6 +467,7 @@ module Puma
|
|
469
467
|
@events.fire(:ping!, w)
|
470
468
|
if !booted && @workers.none? {|worker| worker.last_status.empty?}
|
471
469
|
@events.fire_on_booted!
|
470
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
472
471
|
booted = true
|
473
472
|
end
|
474
473
|
end
|
@@ -478,6 +477,7 @@ module Puma
|
|
478
477
|
end
|
479
478
|
if in_phased_restart && workers_not_booted.zero?
|
480
479
|
@events.fire_on_booted!
|
480
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
481
481
|
in_phased_restart = false
|
482
482
|
end
|
483
483
|
|
data/lib/puma/configuration.rb
CHANGED
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.
|
@@ -100,10 +99,10 @@ module Puma
|
|
100
99
|
# too taxing on performance.
|
101
100
|
module Const
|
102
101
|
|
103
|
-
PUMA_VERSION = VERSION = "6.
|
104
|
-
CODE_NAME = "
|
102
|
+
PUMA_VERSION = VERSION = "6.1.1"
|
103
|
+
CODE_NAME = "The Way Up"
|
105
104
|
|
106
|
-
PUMA_SERVER_STRING = [
|
105
|
+
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
107
106
|
|
108
107
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
109
108
|
|
@@ -112,28 +111,28 @@ module Puma
|
|
112
111
|
WRITE_TIMEOUT = 10
|
113
112
|
|
114
113
|
# The original URI requested by the client.
|
115
|
-
REQUEST_URI=
|
116
|
-
REQUEST_PATH =
|
117
|
-
QUERY_STRING =
|
118
|
-
CONTENT_LENGTH = "CONTENT_LENGTH"
|
114
|
+
REQUEST_URI= "REQUEST_URI"
|
115
|
+
REQUEST_PATH = "REQUEST_PATH"
|
116
|
+
QUERY_STRING = "QUERY_STRING"
|
117
|
+
CONTENT_LENGTH = "CONTENT_LENGTH"
|
119
118
|
|
120
|
-
PATH_INFO =
|
119
|
+
PATH_INFO = "PATH_INFO"
|
121
120
|
|
122
|
-
PUMA_TMP_BASE = "puma"
|
121
|
+
PUMA_TMP_BASE = "puma"
|
123
122
|
|
124
123
|
ERROR_RESPONSE = {
|
125
124
|
# Indicate that we couldn't parse the request
|
126
|
-
400 => "HTTP/1.1 400 Bad Request\r\n\r\n"
|
125
|
+
400 => "HTTP/1.1 400 Bad Request\r\n\r\n",
|
127
126
|
# 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\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND"
|
127
|
+
404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND",
|
129
128
|
# The standard empty 408 response for requests that timed out.
|
130
|
-
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n"
|
129
|
+
408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n",
|
131
130
|
# Indicate that there was an internal error, obviously.
|
132
|
-
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n"
|
131
|
+
500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n",
|
133
132
|
# Incorrect or invalid header value
|
134
|
-
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n"
|
133
|
+
501 => "HTTP/1.1 501 Not Implemented\r\n\r\n",
|
135
134
|
# A common header for indicating the server is too busy. Not used yet.
|
136
|
-
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
|
135
|
+
503 => "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
|
137
136
|
}.freeze
|
138
137
|
|
139
138
|
# The basic max request size we'll try to read.
|
@@ -146,95 +145,88 @@ module Puma
|
|
146
145
|
# Maximum request body size before it is moved out of memory and into a tempfile for reading.
|
147
146
|
MAX_BODY = MAX_HEADER
|
148
147
|
|
149
|
-
REQUEST_METHOD = "REQUEST_METHOD"
|
150
|
-
HEAD = "HEAD"
|
151
|
-
|
152
|
-
POST = "POST".freeze
|
153
|
-
PUT = "PUT".freeze
|
154
|
-
DELETE = "DELETE".freeze
|
155
|
-
OPTIONS = "OPTIONS".freeze
|
156
|
-
TRACE = "TRACE".freeze
|
157
|
-
PATCH = "PATCH".freeze
|
158
|
-
SUPPORTED_HTTP_METHODS = [HEAD, GET, POST, PUT, DELETE, OPTIONS, TRACE, PATCH].freeze
|
148
|
+
REQUEST_METHOD = "REQUEST_METHOD"
|
149
|
+
HEAD = "HEAD"
|
150
|
+
SUPPORTED_HTTP_METHODS = %w[HEAD GET POST PUT DELETE OPTIONS TRACE PATCH].freeze
|
159
151
|
# 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"
|
152
|
+
LINE_END = "\r\n"
|
153
|
+
REMOTE_ADDR = "REMOTE_ADDR"
|
154
|
+
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
155
|
+
HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL"
|
156
|
+
HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME"
|
157
|
+
HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO"
|
166
158
|
|
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 = "::"
|
159
|
+
SERVER_NAME = "SERVER_NAME"
|
160
|
+
SERVER_PORT = "SERVER_PORT"
|
161
|
+
HTTP_HOST = "HTTP_HOST"
|
162
|
+
PORT_80 = "80"
|
163
|
+
PORT_443 = "443"
|
164
|
+
LOCALHOST = "localhost"
|
165
|
+
LOCALHOST_IPV4 = "127.0.0.1"
|
166
|
+
LOCALHOST_IPV6 = "::1"
|
167
|
+
UNSPECIFIED_IPV4 = "0.0.0.0"
|
168
|
+
UNSPECIFIED_IPV6 = "::"
|
177
169
|
|
178
|
-
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
179
|
-
HTTP_11 = "HTTP/1.1"
|
170
|
+
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
171
|
+
HTTP_11 = "HTTP/1.1"
|
180
172
|
|
181
|
-
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
182
|
-
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
183
|
-
CGI_VER = "CGI/1.2"
|
173
|
+
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
174
|
+
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
175
|
+
CGI_VER = "CGI/1.2"
|
184
176
|
|
185
|
-
STOP_COMMAND = "?"
|
186
|
-
HALT_COMMAND = "!"
|
187
|
-
RESTART_COMMAND = "R"
|
177
|
+
STOP_COMMAND = "?"
|
178
|
+
HALT_COMMAND = "!"
|
179
|
+
RESTART_COMMAND = "R"
|
188
180
|
|
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"
|
181
|
+
RACK_INPUT = "rack.input"
|
182
|
+
RACK_URL_SCHEME = "rack.url_scheme"
|
183
|
+
RACK_AFTER_REPLY = "rack.after_reply"
|
184
|
+
PUMA_SOCKET = "puma.socket"
|
185
|
+
PUMA_CONFIG = "puma.config"
|
186
|
+
PUMA_PEERCERT = "puma.peercert"
|
195
187
|
|
196
|
-
HTTP = "http"
|
197
|
-
HTTPS = "https"
|
188
|
+
HTTP = "http"
|
189
|
+
HTTPS = "https"
|
198
190
|
|
199
|
-
HTTPS_KEY = "HTTPS"
|
191
|
+
HTTPS_KEY = "HTTPS"
|
200
192
|
|
201
|
-
HTTP_VERSION = "HTTP_VERSION"
|
202
|
-
HTTP_CONNECTION = "HTTP_CONNECTION"
|
203
|
-
HTTP_EXPECT = "HTTP_EXPECT"
|
204
|
-
CONTINUE = "100-continue"
|
193
|
+
HTTP_VERSION = "HTTP_VERSION"
|
194
|
+
HTTP_CONNECTION = "HTTP_CONNECTION"
|
195
|
+
HTTP_EXPECT = "HTTP_EXPECT"
|
196
|
+
CONTINUE = "100-continue"
|
205
197
|
|
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"
|
198
|
+
HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n"
|
199
|
+
HTTP_11_200 = "HTTP/1.1 200 OK\r\n"
|
200
|
+
HTTP_10_200 = "HTTP/1.0 200 OK\r\n"
|
209
201
|
|
210
|
-
CLOSE = "close"
|
211
|
-
KEEP_ALIVE = "keep-alive"
|
202
|
+
CLOSE = "close"
|
203
|
+
KEEP_ALIVE = "keep-alive"
|
212
204
|
|
213
|
-
CONTENT_LENGTH2 = "content-length"
|
214
|
-
CONTENT_LENGTH_S = "Content-Length: "
|
215
|
-
TRANSFER_ENCODING = "transfer-encoding"
|
216
|
-
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
205
|
+
CONTENT_LENGTH2 = "content-length"
|
206
|
+
CONTENT_LENGTH_S = "Content-Length: "
|
207
|
+
TRANSFER_ENCODING = "transfer-encoding"
|
208
|
+
TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
|
217
209
|
|
218
|
-
CONNECTION_CLOSE = "Connection: close\r\n"
|
219
|
-
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
|
210
|
+
CONNECTION_CLOSE = "Connection: close\r\n"
|
211
|
+
CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
|
220
212
|
|
221
|
-
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
|
222
|
-
CLOSE_CHUNKED = "0\r\n\r\n"
|
213
|
+
TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
|
214
|
+
CLOSE_CHUNKED = "0\r\n\r\n"
|
223
215
|
|
224
|
-
CHUNKED = "chunked"
|
216
|
+
CHUNKED = "chunked"
|
225
217
|
|
226
|
-
COLON = ": "
|
218
|
+
COLON = ": "
|
227
219
|
|
228
|
-
NEWLINE = "\n"
|
220
|
+
NEWLINE = "\n"
|
229
221
|
|
230
|
-
HIJACK_P = "rack.hijack?"
|
231
|
-
HIJACK = "rack.hijack"
|
232
|
-
HIJACK_IO = "rack.hijack_io"
|
222
|
+
HIJACK_P = "rack.hijack?"
|
223
|
+
HIJACK = "rack.hijack"
|
224
|
+
HIJACK_IO = "rack.hijack_io"
|
233
225
|
|
234
|
-
EARLY_HINTS = "rack.early_hints"
|
226
|
+
EARLY_HINTS = "rack.early_hints"
|
235
227
|
|
236
228
|
# Illegal character in the key or value of response header
|
237
|
-
DQUOTE = "\""
|
229
|
+
DQUOTE = "\""
|
238
230
|
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
239
231
|
ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
|
240
232
|
# header values can contain HTAB?
|
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
|
|
@@ -250,6 +251,7 @@ module Puma
|
|
250
251
|
#
|
251
252
|
# * Set the socket backlog depth with +backlog+, default is 1024.
|
252
253
|
# * Set up an SSL certificate with +key+ & +cert+.
|
254
|
+
# * Set up an SSL certificate for mTLS with +key+, +cert+, +ca+ and +verify_mode+.
|
253
255
|
# * Set whether to optimize for low latency instead of throughput with
|
254
256
|
# +low_latency+, default is to not optimize for low latency. This is done
|
255
257
|
# via +Socket::TCP_NODELAY+.
|
@@ -259,6 +261,8 @@ module Puma
|
|
259
261
|
# bind 'unix:///var/run/puma.sock?backlog=512'
|
260
262
|
# @example SSL cert
|
261
263
|
# bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
|
264
|
+
# @example SSL cert for mutual TLS (mTLS)
|
265
|
+
# bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem&ca=ca.pem&verify_mode=force_peer'
|
262
266
|
# @example Disable optimization for low latency
|
263
267
|
# bind 'tcp://0.0.0.0:9292?low_latency=false'
|
264
268
|
# @example Socket permissions
|
@@ -1019,6 +1023,19 @@ module Puma
|
|
1019
1023
|
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
1020
1024
|
end
|
1021
1025
|
|
1026
|
+
# Specify how big the request payload should be, in bytes.
|
1027
|
+
# This limit is compared against Content-Length HTTP header.
|
1028
|
+
# If the payload size (CONTENT_LENGTH) is larger than http_content_length_limit,
|
1029
|
+
# HTTP 413 status code is returned.
|
1030
|
+
#
|
1031
|
+
# When no Content-Length http header is present, it is compared against the
|
1032
|
+
# size of the body of the request.
|
1033
|
+
#
|
1034
|
+
# The default value for http_content_length_limit is nil.
|
1035
|
+
def http_content_length_limit(limit)
|
1036
|
+
@options[:http_content_length_limit] = limit
|
1037
|
+
end
|
1038
|
+
|
1022
1039
|
private
|
1023
1040
|
|
1024
1041
|
# To avoid adding cert_pem and key_pem as URI params, we store them on the
|
data/lib/puma/io_buffer.rb
CHANGED
@@ -22,6 +22,16 @@ module Puma
|
|
22
22
|
read
|
23
23
|
end
|
24
24
|
|
25
|
+
# Read & Reset - returns contents and resets
|
26
|
+
# @return [String] StringIO contents
|
27
|
+
def read_and_reset
|
28
|
+
rewind
|
29
|
+
str = read
|
30
|
+
truncate 0
|
31
|
+
rewind
|
32
|
+
str
|
33
|
+
end
|
34
|
+
|
25
35
|
alias_method :clear, :reset
|
26
36
|
|
27
37
|
# before Ruby 2.5, `write` would only take one argument
|