puma 5.0.4-java → 5.2.2-java
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 +109 -48
- data/README.md +48 -18
- data/docs/architecture.md +21 -18
- data/docs/compile_options.md +19 -0
- data/docs/deployment.md +1 -1
- data/docs/fork_worker.md +2 -0
- data/docs/kubernetes.md +66 -0
- data/docs/plugins.md +1 -1
- data/docs/rails_dev_mode.md +29 -0
- data/docs/stats.md +142 -0
- data/docs/systemd.md +24 -2
- data/ext/puma_http11/extconf.rb +18 -5
- data/ext/puma_http11/http11_parser.c +45 -47
- data/ext/puma_http11/http11_parser.java.rl +1 -1
- data/ext/puma_http11/http11_parser.rl +1 -1
- data/ext/puma_http11/mini_ssl.c +162 -84
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +5 -7
- data/ext/puma_http11/puma_http11.c +8 -2
- data/lib/puma.rb +20 -10
- data/lib/puma/app/status.rb +4 -7
- data/lib/puma/binder.rb +60 -24
- data/lib/puma/cli.rb +4 -0
- data/lib/puma/client.rb +4 -9
- data/lib/puma/cluster.rb +10 -6
- data/lib/puma/cluster/worker.rb +8 -2
- data/lib/puma/cluster/worker_handle.rb +5 -2
- data/lib/puma/configuration.rb +14 -1
- data/lib/puma/const.rb +11 -3
- data/lib/puma/control_cli.rb +73 -70
- data/lib/puma/detect.rb +14 -10
- data/lib/puma/dsl.rb +104 -22
- data/lib/puma/error_logger.rb +10 -3
- data/lib/puma/events.rb +18 -3
- data/lib/puma/json.rb +96 -0
- data/lib/puma/launcher.rb +52 -6
- data/lib/puma/minissl.rb +48 -17
- data/lib/puma/minissl/context_builder.rb +6 -0
- data/lib/puma/null_io.rb +12 -0
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/reactor.rb +19 -12
- data/lib/puma/request.rb +20 -7
- data/lib/puma/runner.rb +19 -7
- data/lib/puma/server.rb +20 -75
- data/lib/puma/state_file.rb +5 -3
- data/lib/puma/systemd.rb +46 -0
- data/lib/rack/handler/puma.rb +1 -0
- metadata +8 -2
data/lib/puma/minissl.rb
CHANGED
@@ -73,7 +73,6 @@ module Puma
|
|
73
73
|
|
74
74
|
def engine_read_all
|
75
75
|
output = @engine.read
|
76
|
-
raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
|
77
76
|
while output and additional_output = @engine.read
|
78
77
|
output << additional_output
|
79
78
|
end
|
@@ -100,6 +99,7 @@ module Puma
|
|
100
99
|
# ourselves.
|
101
100
|
raise IO::EAGAINWaitReadable
|
102
101
|
elsif data.nil?
|
102
|
+
raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
|
103
103
|
return nil
|
104
104
|
end
|
105
105
|
|
@@ -117,22 +117,23 @@ module Puma
|
|
117
117
|
def write(data)
|
118
118
|
return 0 if data.empty?
|
119
119
|
|
120
|
-
|
120
|
+
data_size = data.bytesize
|
121
|
+
need = data_size
|
121
122
|
|
122
123
|
while true
|
123
124
|
wrote = @engine.write data
|
124
|
-
enc = @engine.extract
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
enc_wr = ''.dup
|
127
|
+
while (enc = @engine.extract)
|
128
|
+
enc_wr << enc
|
129
129
|
end
|
130
|
+
@socket.write enc_wr unless enc_wr.empty?
|
130
131
|
|
131
132
|
need -= wrote
|
132
133
|
|
133
|
-
return
|
134
|
+
return data_size if need == 0
|
134
135
|
|
135
|
-
data = data
|
136
|
+
data = data.byteslice(wrote..-1)
|
136
137
|
end
|
137
138
|
end
|
138
139
|
|
@@ -245,6 +246,7 @@ module Puma
|
|
245
246
|
attr_reader :cert
|
246
247
|
attr_reader :ca
|
247
248
|
attr_accessor :ssl_cipher_filter
|
249
|
+
attr_accessor :verification_flags
|
248
250
|
|
249
251
|
def key=(key)
|
250
252
|
raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
|
@@ -287,33 +289,58 @@ module Puma
|
|
287
289
|
VERIFY_PEER = 1
|
288
290
|
VERIFY_FAIL_IF_NO_PEER_CERT = 2
|
289
291
|
|
292
|
+
# https://github.com/openssl/openssl/blob/master/include/openssl/x509_vfy.h.in
|
293
|
+
# /* Certificate verify flags */
|
294
|
+
VERIFICATION_FLAGS = {
|
295
|
+
"USE_CHECK_TIME" => 0x2,
|
296
|
+
"CRL_CHECK" => 0x4,
|
297
|
+
"CRL_CHECK_ALL" => 0x8,
|
298
|
+
"IGNORE_CRITICAL" => 0x10,
|
299
|
+
"X509_STRICT" => 0x20,
|
300
|
+
"ALLOW_PROXY_CERTS" => 0x40,
|
301
|
+
"POLICY_CHECK" => 0x80,
|
302
|
+
"EXPLICIT_POLICY" => 0x100,
|
303
|
+
"INHIBIT_ANY" => 0x200,
|
304
|
+
"INHIBIT_MAP" => 0x400,
|
305
|
+
"NOTIFY_POLICY" => 0x800,
|
306
|
+
"EXTENDED_CRL_SUPPORT" => 0x1000,
|
307
|
+
"USE_DELTAS" => 0x2000,
|
308
|
+
"CHECK_SS_SIGNATURE" => 0x4000,
|
309
|
+
"TRUSTED_FIRST" => 0x8000,
|
310
|
+
"SUITEB_128_LOS_ONLY" => 0x10000,
|
311
|
+
"SUITEB_192_LOS" => 0x20000,
|
312
|
+
"SUITEB_128_LOS" => 0x30000,
|
313
|
+
"PARTIAL_CHAIN" => 0x80000,
|
314
|
+
"NO_ALT_CHAINS" => 0x100000,
|
315
|
+
"NO_CHECK_TIME" => 0x200000
|
316
|
+
}.freeze
|
317
|
+
|
290
318
|
class Server
|
291
319
|
def initialize(socket, ctx)
|
292
320
|
@socket = socket
|
293
321
|
@ctx = ctx
|
294
|
-
|
295
|
-
|
296
|
-
# @!attribute [r] to_io
|
297
|
-
def to_io
|
298
|
-
@socket
|
322
|
+
@eng_ctx = IS_JRUBY ? @ctx : SSLContext.new(ctx)
|
299
323
|
end
|
300
324
|
|
301
325
|
def accept
|
302
326
|
@ctx.check
|
303
327
|
io = @socket.accept
|
304
|
-
engine = Engine.server @
|
305
|
-
|
328
|
+
engine = Engine.server @eng_ctx
|
306
329
|
Socket.new io, engine
|
307
330
|
end
|
308
331
|
|
309
332
|
def accept_nonblock
|
310
333
|
@ctx.check
|
311
334
|
io = @socket.accept_nonblock
|
312
|
-
engine = Engine.server @
|
313
|
-
|
335
|
+
engine = Engine.server @eng_ctx
|
314
336
|
Socket.new io, engine
|
315
337
|
end
|
316
338
|
|
339
|
+
# @!attribute [r] to_io
|
340
|
+
def to_io
|
341
|
+
@socket
|
342
|
+
end
|
343
|
+
|
317
344
|
# @!attribute [r] addr
|
318
345
|
# @version 5.0.0
|
319
346
|
def addr
|
@@ -323,6 +350,10 @@ module Puma
|
|
323
350
|
def close
|
324
351
|
@socket.close unless @socket.closed? # closed? call is for Windows
|
325
352
|
end
|
353
|
+
|
354
|
+
def closed?
|
355
|
+
@socket.closed?
|
356
|
+
end
|
326
357
|
end
|
327
358
|
end
|
328
359
|
end
|
@@ -62,6 +62,12 @@ module Puma
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
if params['verification_flags']
|
66
|
+
ctx.verification_flags = params['verification_flags'].split(',').
|
67
|
+
map { |flag| MiniSSL::VERIFICATION_FLAGS.fetch(flag) }.
|
68
|
+
inject { |sum, flag| sum ? sum | flag : flag }
|
69
|
+
end
|
70
|
+
|
65
71
|
ctx
|
66
72
|
end
|
67
73
|
|
data/lib/puma/null_io.rb
CHANGED
@@ -9,6 +9,10 @@ module Puma
|
|
9
9
|
nil
|
10
10
|
end
|
11
11
|
|
12
|
+
def string
|
13
|
+
""
|
14
|
+
end
|
15
|
+
|
12
16
|
def each
|
13
17
|
end
|
14
18
|
|
@@ -32,6 +36,10 @@ module Puma
|
|
32
36
|
true
|
33
37
|
end
|
34
38
|
|
39
|
+
def sync
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
35
43
|
def sync=(v)
|
36
44
|
end
|
37
45
|
|
@@ -40,5 +48,9 @@ module Puma
|
|
40
48
|
|
41
49
|
def write(*ary)
|
42
50
|
end
|
51
|
+
|
52
|
+
def flush
|
53
|
+
self
|
54
|
+
end
|
43
55
|
end
|
44
56
|
end
|
data/lib/puma/puma_http11.jar
CHANGED
Binary file
|
data/lib/puma/reactor.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require 'puma/queue_close' unless ::Queue.instance_methods.include? :close
|
4
4
|
|
5
5
|
module Puma
|
6
|
+
class UnsupportedBackend < StandardError; end
|
7
|
+
|
6
8
|
# Monitors a collection of IO objects, calling a block whenever
|
7
9
|
# any monitored object either receives data or times out, or when the Reactor shuts down.
|
8
10
|
#
|
@@ -18,9 +20,12 @@ module Puma
|
|
18
20
|
# Create a new Reactor to monitor IO objects added by #add.
|
19
21
|
# The provided block will be invoked when an IO has data available to read,
|
20
22
|
# its timeout elapses, or when the Reactor shuts down.
|
21
|
-
def initialize(&block)
|
23
|
+
def initialize(backend, &block)
|
22
24
|
require 'nio'
|
23
|
-
|
25
|
+
unless backend == :auto || NIO::Selector.backends.include?(backend)
|
26
|
+
raise "unsupported IO selector backend: #{backend} (available backends: #{NIO::Selector.backends.join(', ')})"
|
27
|
+
end
|
28
|
+
@selector = backend == :auto ? NIO::Selector.new : NIO::Selector.new(backend)
|
24
29
|
@input = Queue.new
|
25
30
|
@timeouts = []
|
26
31
|
@block = block
|
@@ -38,11 +43,11 @@ module Puma
|
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
41
|
-
# Add a new
|
46
|
+
# Add a new client to monitor.
|
42
47
|
# The object must respond to #timeout and #timeout_at.
|
43
48
|
# Returns false if the reactor is already shut down.
|
44
|
-
def add(
|
45
|
-
@input <<
|
49
|
+
def add(client)
|
50
|
+
@input << client
|
46
51
|
@selector.wakeup
|
47
52
|
true
|
48
53
|
rescue ClosedQueueError
|
@@ -92,17 +97,19 @@ module Puma
|
|
92
97
|
end
|
93
98
|
|
94
99
|
# Start monitoring the object.
|
95
|
-
def register(
|
96
|
-
@selector.register(
|
97
|
-
@timeouts <<
|
100
|
+
def register(client)
|
101
|
+
@selector.register(client.to_io, :r).value = client
|
102
|
+
@timeouts << client
|
103
|
+
rescue ArgumentError
|
104
|
+
# unreadable clients raise error when processed by NIO
|
98
105
|
end
|
99
106
|
|
100
107
|
# 'Wake up' a monitored object by calling the provided block.
|
101
108
|
# Stop monitoring the object if the block returns `true`.
|
102
|
-
def wakeup!(
|
103
|
-
if @block.call
|
104
|
-
@selector.deregister
|
105
|
-
@timeouts.delete
|
109
|
+
def wakeup!(client)
|
110
|
+
if @block.call client
|
111
|
+
@selector.deregister client.to_io
|
112
|
+
@timeouts.delete client
|
106
113
|
end
|
107
114
|
end
|
108
115
|
end
|
data/lib/puma/request.rb
CHANGED
@@ -30,7 +30,7 @@ module Puma
|
|
30
30
|
#
|
31
31
|
def handle_request(client, lines)
|
32
32
|
env = client.env
|
33
|
-
io
|
33
|
+
io = client.io # io may be a MiniSSL::Socket
|
34
34
|
|
35
35
|
return false if closed_socket?(io)
|
36
36
|
|
@@ -282,13 +282,20 @@ module Puma
|
|
282
282
|
end
|
283
283
|
# private :normalize_env
|
284
284
|
|
285
|
+
# @param header_key [#to_s]
|
286
|
+
# @return [Boolean]
|
287
|
+
#
|
288
|
+
def illegal_header_key?(header_key)
|
289
|
+
!!(ILLEGAL_HEADER_KEY_REGEX =~ header_key.to_s)
|
290
|
+
end
|
291
|
+
|
285
292
|
# @param header_value [#to_s]
|
286
293
|
# @return [Boolean]
|
287
294
|
#
|
288
|
-
def
|
289
|
-
!!(
|
295
|
+
def illegal_header_value?(header_value)
|
296
|
+
!!(ILLEGAL_HEADER_VALUE_REGEX =~ header_value.to_s)
|
290
297
|
end
|
291
|
-
private :
|
298
|
+
private :illegal_header_key?, :illegal_header_value?
|
292
299
|
|
293
300
|
# Fixup any headers with `,` in the name to have `_` now. We emit
|
294
301
|
# headers with `,` in them during the parse phase to avoid ambiguity
|
@@ -334,9 +341,11 @@ module Puma
|
|
334
341
|
def str_early_hints(headers)
|
335
342
|
eh_str = "HTTP/1.1 103 Early Hints\r\n".dup
|
336
343
|
headers.each_pair do |k, vs|
|
344
|
+
next if illegal_header_key?(k)
|
345
|
+
|
337
346
|
if vs.respond_to?(:to_s) && !vs.to_s.empty?
|
338
347
|
vs.to_s.split(NEWLINE).each do |v|
|
339
|
-
next if
|
348
|
+
next if illegal_header_value?(v)
|
340
349
|
eh_str << "#{k}: #{v}\r\n"
|
341
350
|
end
|
342
351
|
else
|
@@ -399,9 +408,11 @@ module Puma
|
|
399
408
|
res_info[:response_hijack] = nil
|
400
409
|
|
401
410
|
headers.each do |k, vs|
|
411
|
+
next if illegal_header_key?(k)
|
412
|
+
|
402
413
|
case k.downcase
|
403
414
|
when CONTENT_LENGTH2
|
404
|
-
next if
|
415
|
+
next if illegal_header_value?(vs)
|
405
416
|
res_info[:content_length] = vs
|
406
417
|
next
|
407
418
|
when TRANSFER_ENCODING
|
@@ -410,11 +421,13 @@ module Puma
|
|
410
421
|
when HIJACK
|
411
422
|
res_info[:response_hijack] = vs
|
412
423
|
next
|
424
|
+
when BANNED_HEADER_KEY
|
425
|
+
next
|
413
426
|
end
|
414
427
|
|
415
428
|
if vs.respond_to?(:to_s) && !vs.to_s.empty?
|
416
429
|
vs.to_s.split(NEWLINE).each do |v|
|
417
|
-
next if
|
430
|
+
next if illegal_header_value?(v)
|
418
431
|
lines.append k, colon, v, line_ending
|
419
432
|
end
|
420
433
|
else
|
data/lib/puma/runner.rb
CHANGED
@@ -55,11 +55,11 @@ module Puma
|
|
55
55
|
app = Puma::App::Status.new @launcher, token
|
56
56
|
|
57
57
|
control = Puma::Server.new app, @launcher.events,
|
58
|
-
{ min_threads: 0, max_threads: 1 }
|
58
|
+
{ min_threads: 0, max_threads: 1, queue_requests: false }
|
59
59
|
|
60
60
|
control.binder.parse [str], self, 'Starting control server'
|
61
61
|
|
62
|
-
control.run
|
62
|
+
control.run thread_name: 'control'
|
63
63
|
@control = control
|
64
64
|
end
|
65
65
|
|
@@ -86,9 +86,16 @@ module Puma
|
|
86
86
|
max_t = @options[:max_threads]
|
87
87
|
|
88
88
|
log "Puma starting in #{mode} mode..."
|
89
|
-
log "*
|
90
|
-
log "*
|
91
|
-
log "*
|
89
|
+
log "* Puma version: #{Puma::Const::PUMA_VERSION} (#{ruby_engine}) (\"#{Puma::Const::CODE_NAME}\")"
|
90
|
+
log "* Min threads: #{min_t}"
|
91
|
+
log "* Max threads: #{max_t}"
|
92
|
+
log "* Environment: #{ENV['RACK_ENV']}"
|
93
|
+
|
94
|
+
if mode == "cluster"
|
95
|
+
log "* Master PID: #{Process.pid}"
|
96
|
+
else
|
97
|
+
log "* PID: #{Process.pid}"
|
98
|
+
end
|
92
99
|
end
|
93
100
|
|
94
101
|
def redirected_io?
|
@@ -106,8 +113,8 @@ module Puma
|
|
106
113
|
end
|
107
114
|
|
108
115
|
STDOUT.reopen stdout, (append ? "a" : "w")
|
109
|
-
STDOUT.sync = true
|
110
116
|
STDOUT.puts "=== puma startup: #{Time.now} ==="
|
117
|
+
STDOUT.flush unless STDOUT.sync
|
111
118
|
end
|
112
119
|
|
113
120
|
if stderr
|
@@ -116,8 +123,13 @@ module Puma
|
|
116
123
|
end
|
117
124
|
|
118
125
|
STDERR.reopen stderr, (append ? "a" : "w")
|
119
|
-
STDERR.sync = true
|
120
126
|
STDERR.puts "=== puma startup: #{Time.now} ==="
|
127
|
+
STDERR.flush unless STDERR.sync
|
128
|
+
end
|
129
|
+
|
130
|
+
if @options[:mutate_stdout_and_stderr_to_sync_on_write]
|
131
|
+
STDOUT.sync = true
|
132
|
+
STDERR.sync = true
|
121
133
|
end
|
122
134
|
end
|
123
135
|
|
data/lib/puma/server.rb
CHANGED
@@ -84,12 +84,14 @@ module Puma
|
|
84
84
|
|
85
85
|
@options = options
|
86
86
|
|
87
|
-
@early_hints
|
88
|
-
@first_data_timeout
|
89
|
-
@min_threads
|
90
|
-
@max_threads
|
91
|
-
@persistent_timeout
|
92
|
-
@queue_requests
|
87
|
+
@early_hints = options.fetch :early_hints, nil
|
88
|
+
@first_data_timeout = options.fetch :first_data_timeout, FIRST_DATA_TIMEOUT
|
89
|
+
@min_threads = options.fetch :min_threads, 0
|
90
|
+
@max_threads = options.fetch :max_threads , (Puma.mri? ? 5 : 16)
|
91
|
+
@persistent_timeout = options.fetch :persistent_timeout, PERSISTENT_TIMEOUT
|
92
|
+
@queue_requests = options.fetch :queue_requests, true
|
93
|
+
@max_fast_inline = options.fetch :max_fast_inline, MAX_FAST_INLINE
|
94
|
+
@io_selector_backend = options.fetch :io_selector_backend, :auto
|
93
95
|
|
94
96
|
temp = !!(@options[:environment] =~ /\A(development|test)\z/)
|
95
97
|
@leak_stack_on_error = @options[:environment] ? temp : true
|
@@ -118,17 +120,13 @@ module Puma
|
|
118
120
|
# :nodoc:
|
119
121
|
# @version 5.0.0
|
120
122
|
def tcp_cork_supported?
|
121
|
-
|
122
|
-
Socket.const_defined?(:IPPROTO_TCP) &&
|
123
|
-
Socket.const_defined?(:TCP_CORK)
|
123
|
+
Socket.const_defined?(:TCP_CORK) && Socket.const_defined?(:IPPROTO_TCP)
|
124
124
|
end
|
125
125
|
|
126
126
|
# :nodoc:
|
127
127
|
# @version 5.0.0
|
128
128
|
def closed_socket_supported?
|
129
|
-
|
130
|
-
Socket.const_defined?(:IPPROTO_TCP) &&
|
131
|
-
Socket.const_defined?(:TCP_INFO)
|
129
|
+
Socket.const_defined?(:TCP_INFO) && Socket.const_defined?(:IPPROTO_TCP)
|
132
130
|
end
|
133
131
|
private :tcp_cork_supported?
|
134
132
|
private :closed_socket_supported?
|
@@ -136,6 +134,7 @@ module Puma
|
|
136
134
|
|
137
135
|
# On Linux, use TCP_CORK to better control how the TCP stack
|
138
136
|
# packetizes our stream. This improves both latency and throughput.
|
137
|
+
# socket parameter may be an MiniSSL::Socket, so use to_io
|
139
138
|
#
|
140
139
|
if tcp_cork_supported?
|
141
140
|
UNPACK_TCP_STATE_FROM_TCP_INFO = "C".freeze
|
@@ -144,16 +143,18 @@ module Puma
|
|
144
143
|
# 3 == TCP_CORK
|
145
144
|
# 1/0 == turn on/off
|
146
145
|
def cork_socket(socket)
|
146
|
+
skt = socket.to_io
|
147
147
|
begin
|
148
|
-
|
148
|
+
skt.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_CORK, 1) if skt.kind_of? TCPSocket
|
149
149
|
rescue IOError, SystemCallError
|
150
150
|
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
154
|
def uncork_socket(socket)
|
155
|
+
skt = socket.to_io
|
155
156
|
begin
|
156
|
-
|
157
|
+
skt.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_CORK, 0) if skt.kind_of? TCPSocket
|
157
158
|
rescue IOError, SystemCallError
|
158
159
|
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
159
160
|
end
|
@@ -218,7 +219,7 @@ module Puma
|
|
218
219
|
# up in the background to handle requests. Otherwise requests
|
219
220
|
# are handled synchronously.
|
220
221
|
#
|
221
|
-
def run(background=true)
|
222
|
+
def run(background=true, thread_name: 'server')
|
222
223
|
BasicSocket.do_not_reverse_lookup = true
|
223
224
|
|
224
225
|
@events.fire :state, :booting
|
@@ -236,7 +237,7 @@ module Puma
|
|
236
237
|
@thread_pool.clean_thread_locals = @options[:clean_thread_locals]
|
237
238
|
|
238
239
|
if @queue_requests
|
239
|
-
@reactor = Reactor.new(&method(:reactor_wakeup))
|
240
|
+
@reactor = Reactor.new(@io_selector_backend, &method(:reactor_wakeup))
|
240
241
|
@reactor.run
|
241
242
|
end
|
242
243
|
|
@@ -254,7 +255,7 @@ module Puma
|
|
254
255
|
|
255
256
|
if background
|
256
257
|
@thread = Thread.new do
|
257
|
-
Puma.set_thread_name
|
258
|
+
Puma.set_thread_name thread_name
|
258
259
|
handle_servers
|
259
260
|
end
|
260
261
|
return @thread
|
@@ -442,11 +443,11 @@ module Puma
|
|
442
443
|
|
443
444
|
check_for_more_data = @status == :run
|
444
445
|
|
445
|
-
if requests >=
|
446
|
+
if requests >= @max_fast_inline
|
446
447
|
# This will mean that reset will only try to use the data it already
|
447
448
|
# has buffered and won't try to read more data. What this means is that
|
448
449
|
# every client, independent of their request speed, gets treated like a slow
|
449
|
-
# one once every
|
450
|
+
# one once every max_fast_inline requests.
|
450
451
|
check_for_more_data = false
|
451
452
|
end
|
452
453
|
|
@@ -493,62 +494,6 @@ module Puma
|
|
493
494
|
|
494
495
|
# :nocov:
|
495
496
|
|
496
|
-
# Given the request +env+ from +client+ and the partial body +body+
|
497
|
-
# plus a potential Content-Length value +cl+, finish reading
|
498
|
-
# the body and return it.
|
499
|
-
#
|
500
|
-
# If the body is larger than MAX_BODY, a Tempfile object is used
|
501
|
-
# for the body, otherwise a StringIO is used.
|
502
|
-
# @deprecated 6.0.0
|
503
|
-
#
|
504
|
-
def read_body(env, client, body, cl)
|
505
|
-
content_length = cl.to_i
|
506
|
-
|
507
|
-
remain = content_length - body.bytesize
|
508
|
-
|
509
|
-
return StringIO.new(body) if remain <= 0
|
510
|
-
|
511
|
-
# Use a Tempfile if there is a lot of data left
|
512
|
-
if remain > MAX_BODY
|
513
|
-
stream = Tempfile.new(Const::PUMA_TMP_BASE)
|
514
|
-
stream.binmode
|
515
|
-
else
|
516
|
-
# The body[0,0] trick is to get an empty string in the same
|
517
|
-
# encoding as body.
|
518
|
-
stream = StringIO.new body[0,0]
|
519
|
-
end
|
520
|
-
|
521
|
-
stream.write body
|
522
|
-
|
523
|
-
# Read an odd sized chunk so we can read even sized ones
|
524
|
-
# after this
|
525
|
-
chunk = client.readpartial(remain % CHUNK_SIZE)
|
526
|
-
|
527
|
-
# No chunk means a closed socket
|
528
|
-
unless chunk
|
529
|
-
stream.close
|
530
|
-
return nil
|
531
|
-
end
|
532
|
-
|
533
|
-
remain -= stream.write(chunk)
|
534
|
-
|
535
|
-
# Read the rest of the chunks
|
536
|
-
while remain > 0
|
537
|
-
chunk = client.readpartial(CHUNK_SIZE)
|
538
|
-
unless chunk
|
539
|
-
stream.close
|
540
|
-
return nil
|
541
|
-
end
|
542
|
-
|
543
|
-
remain -= stream.write(chunk)
|
544
|
-
end
|
545
|
-
|
546
|
-
stream.rewind
|
547
|
-
|
548
|
-
return stream
|
549
|
-
end
|
550
|
-
# :nocov:
|
551
|
-
|
552
497
|
# Handle various error types thrown by Client I/O operations.
|
553
498
|
def client_error(e, client)
|
554
499
|
# Swallow, do not log
|