puma 3.11.3 → 4.0.0
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 +5 -5
- data/History.md +61 -0
- data/README.md +41 -11
- data/docs/architecture.md +2 -1
- data/docs/deployment.md +24 -4
- data/docs/restart.md +5 -3
- data/docs/systemd.md +37 -9
- data/ext/puma_http11/PumaHttp11Service.java +2 -0
- data/ext/puma_http11/mini_ssl.c +42 -5
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +17 -4
- data/lib/puma.rb +8 -0
- data/lib/puma/app/status.rb +3 -2
- data/lib/puma/binder.rb +22 -10
- data/lib/puma/cli.rb +18 -7
- data/lib/puma/client.rb +54 -22
- data/lib/puma/cluster.rb +54 -15
- data/lib/puma/commonlogger.rb +2 -0
- data/lib/puma/configuration.rb +4 -1
- data/lib/puma/const.rb +8 -2
- data/lib/puma/control_cli.rb +23 -11
- data/lib/puma/convenient.rb +2 -0
- data/lib/puma/daemon_ext.rb +2 -0
- data/lib/puma/delegation.rb +2 -0
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +63 -11
- data/lib/puma/events.rb +2 -0
- data/lib/puma/io_buffer.rb +3 -6
- data/lib/puma/jruby_restart.rb +2 -0
- data/lib/puma/launcher.rb +15 -13
- data/lib/puma/minissl.rb +20 -4
- data/lib/puma/null_io.rb +2 -0
- data/lib/puma/plugin.rb +2 -0
- data/lib/puma/rack/builder.rb +2 -1
- data/lib/puma/reactor.rb +215 -30
- data/lib/puma/runner.rb +11 -2
- data/lib/puma/server.rb +63 -26
- data/lib/puma/single.rb +14 -3
- data/lib/puma/state_file.rb +2 -0
- data/lib/puma/tcp_logger.rb +2 -0
- data/lib/puma/thread_pool.rb +50 -5
- data/lib/puma/util.rb +2 -6
- data/lib/rack/handler/puma.rb +4 -0
- data/tools/jungle/README.md +10 -4
- data/tools/jungle/init.d/README.md +2 -0
- data/tools/jungle/init.d/puma +7 -7
- data/tools/jungle/init.d/run-puma +1 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- metadata +23 -9
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
@@ -0,0 +1,72 @@
|
|
1
|
+
package org.jruby.puma;
|
2
|
+
|
3
|
+
import org.jruby.*;
|
4
|
+
import org.jruby.anno.JRubyMethod;
|
5
|
+
import org.jruby.runtime.ObjectAllocator;
|
6
|
+
import org.jruby.runtime.ThreadContext;
|
7
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
8
|
+
import org.jruby.util.ByteList;
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @author kares
|
12
|
+
*/
|
13
|
+
public class IOBuffer extends RubyObject {
|
14
|
+
|
15
|
+
private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
16
|
+
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
17
|
+
return new IOBuffer(runtime, klass);
|
18
|
+
}
|
19
|
+
};
|
20
|
+
|
21
|
+
public static void createIOBuffer(Ruby runtime) {
|
22
|
+
RubyModule mPuma = runtime.defineModule("Puma");
|
23
|
+
RubyClass cIOBuffer = mPuma.defineClassUnder("IOBuffer", runtime.getObject(), ALLOCATOR);
|
24
|
+
cIOBuffer.defineAnnotatedMethods(IOBuffer.class);
|
25
|
+
}
|
26
|
+
|
27
|
+
private static final int DEFAULT_SIZE = 4096;
|
28
|
+
|
29
|
+
final ByteList buffer = new ByteList(DEFAULT_SIZE);
|
30
|
+
|
31
|
+
IOBuffer(Ruby runtime, RubyClass klass) {
|
32
|
+
super(runtime, klass);
|
33
|
+
}
|
34
|
+
|
35
|
+
@JRubyMethod
|
36
|
+
public RubyInteger used(ThreadContext context) {
|
37
|
+
return context.runtime.newFixnum(buffer.getRealSize());
|
38
|
+
}
|
39
|
+
|
40
|
+
@JRubyMethod
|
41
|
+
public RubyInteger capacity(ThreadContext context) {
|
42
|
+
return context.runtime.newFixnum(buffer.unsafeBytes().length);
|
43
|
+
}
|
44
|
+
|
45
|
+
@JRubyMethod
|
46
|
+
public IRubyObject reset() {
|
47
|
+
buffer.setRealSize(0);
|
48
|
+
return this;
|
49
|
+
}
|
50
|
+
|
51
|
+
@JRubyMethod(name = { "to_s", "to_str" })
|
52
|
+
public RubyString to_s(ThreadContext context) {
|
53
|
+
return RubyString.newStringShared(context.runtime, buffer.unsafeBytes(), 0, buffer.getRealSize());
|
54
|
+
}
|
55
|
+
|
56
|
+
@JRubyMethod(name = "<<")
|
57
|
+
public IRubyObject add(IRubyObject str) {
|
58
|
+
addImpl(str.convertToString());
|
59
|
+
return this;
|
60
|
+
}
|
61
|
+
|
62
|
+
@JRubyMethod(rest = true)
|
63
|
+
public IRubyObject append(IRubyObject[] strs) {
|
64
|
+
for (IRubyObject str : strs) addImpl(str.convertToString());
|
65
|
+
return this;
|
66
|
+
}
|
67
|
+
|
68
|
+
private void addImpl(RubyString str) {
|
69
|
+
buffer.append(str.getByteList());
|
70
|
+
}
|
71
|
+
|
72
|
+
}
|
@@ -23,6 +23,7 @@ import javax.net.ssl.SSLPeerUnverifiedException;
|
|
23
23
|
import javax.net.ssl.SSLSession;
|
24
24
|
import java.io.FileInputStream;
|
25
25
|
import java.io.IOException;
|
26
|
+
import java.nio.Buffer;
|
26
27
|
import java.nio.ByteBuffer;
|
27
28
|
import java.security.KeyManagementException;
|
28
29
|
import java.security.KeyStore;
|
@@ -65,7 +66,7 @@ public class MiniSSL extends RubyObject {
|
|
65
66
|
|
66
67
|
public void clear() { buffer.clear(); }
|
67
68
|
public void compact() { buffer.compact(); }
|
68
|
-
public void flip() { buffer.flip(); }
|
69
|
+
public void flip() { ((Buffer) buffer).flip(); }
|
69
70
|
public boolean hasRemaining() { return buffer.hasRemaining(); }
|
70
71
|
public int position() { return buffer.position(); }
|
71
72
|
|
@@ -89,7 +90,7 @@ public class MiniSSL extends RubyObject {
|
|
89
90
|
public void resize(int newCapacity) {
|
90
91
|
if (newCapacity > buffer.capacity()) {
|
91
92
|
ByteBuffer dstTmp = ByteBuffer.allocate(newCapacity);
|
92
|
-
|
93
|
+
flip();
|
93
94
|
dstTmp.put(buffer);
|
94
95
|
buffer = dstTmp;
|
95
96
|
} else {
|
@@ -101,7 +102,7 @@ public class MiniSSL extends RubyObject {
|
|
101
102
|
* Drains the buffer to a ByteList, or returns null for an empty buffer
|
102
103
|
*/
|
103
104
|
public ByteList asByteList() {
|
104
|
-
|
105
|
+
flip();
|
105
106
|
if (!buffer.hasRemaining()) {
|
106
107
|
buffer.clear();
|
107
108
|
return null;
|
@@ -158,7 +159,13 @@ public class MiniSSL extends RubyObject {
|
|
158
159
|
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
159
160
|
engine = sslCtx.createSSLEngine();
|
160
161
|
|
161
|
-
String[] protocols
|
162
|
+
String[] protocols;
|
163
|
+
if(miniSSLContext.callMethod(threadContext, "no_tlsv1").isTrue()) {
|
164
|
+
protocols = new String[] { "TLSv1.1", "TLSv1.2" };
|
165
|
+
} else {
|
166
|
+
protocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" };
|
167
|
+
}
|
168
|
+
|
162
169
|
engine.setEnabledProtocols(protocols);
|
163
170
|
engine.setUseClientMode(false);
|
164
171
|
|
@@ -170,6 +177,12 @@ public class MiniSSL extends RubyObject {
|
|
170
177
|
engine.setNeedClientAuth(true);
|
171
178
|
}
|
172
179
|
|
180
|
+
IRubyObject sslCipherListObject = miniSSLContext.callMethod(threadContext, "ssl_cipher_list");
|
181
|
+
if (!sslCipherListObject.isNil()) {
|
182
|
+
String[] sslCipherList = sslCipherListObject.convertToString().asJavaString().split(",");
|
183
|
+
engine.setEnabledCipherSuites(sslCipherList);
|
184
|
+
}
|
185
|
+
|
173
186
|
SSLSession session = engine.getSession();
|
174
187
|
inboundNetData = new MiniSSLBuffer(session.getPacketBufferSize());
|
175
188
|
outboundAppData = new MiniSSLBuffer(session.getApplicationBufferSize());
|
data/lib/puma.rb
CHANGED
data/lib/puma/app/status.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
1
3
|
module Puma
|
2
4
|
module App
|
3
5
|
class Status
|
@@ -60,8 +62,7 @@ module Puma
|
|
60
62
|
return rack_response(200, OK_STATUS)
|
61
63
|
|
62
64
|
when /\/gc-stats$/
|
63
|
-
|
64
|
-
return rack_response(200, json)
|
65
|
+
return rack_response(200, GC.stat.to_json)
|
65
66
|
|
66
67
|
when /\/stats$/
|
67
68
|
return rack_response(200, @cli.stats)
|
data/lib/puma/binder.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
require 'socket'
|
3
5
|
|
@@ -48,7 +50,13 @@ module Puma
|
|
48
50
|
|
49
51
|
def close
|
50
52
|
@ios.each { |i| i.close }
|
51
|
-
@unix_paths.each
|
53
|
+
@unix_paths.each do |i|
|
54
|
+
# Errno::ENOENT is intermittently raised
|
55
|
+
begin
|
56
|
+
File.unlink i
|
57
|
+
rescue Errno::ENOENT
|
58
|
+
end
|
59
|
+
end
|
52
60
|
end
|
53
61
|
|
54
62
|
def import_from_env
|
@@ -90,19 +98,19 @@ module Puma
|
|
90
98
|
case uri.scheme
|
91
99
|
when "tcp"
|
92
100
|
if fd = @inherited_fds.delete(str)
|
93
|
-
logger.log "* Inherited #{str}"
|
94
101
|
io = inherit_tcp_listener uri.host, uri.port, fd
|
102
|
+
logger.log "* Inherited #{str}"
|
95
103
|
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
|
96
|
-
logger.log "* Activated #{str}"
|
97
104
|
io = inherit_tcp_listener uri.host, uri.port, sock
|
105
|
+
logger.log "* Activated #{str}"
|
98
106
|
else
|
99
107
|
params = Util.parse_query uri.query
|
100
108
|
|
101
109
|
opt = params.key?('low_latency')
|
102
110
|
bak = params.fetch('backlog', 1024).to_i
|
103
111
|
|
104
|
-
logger.log "* Listening on #{str}"
|
105
112
|
io = add_tcp_listener uri.host, uri.port, opt, bak
|
113
|
+
logger.log "* Listening on #{str}"
|
106
114
|
end
|
107
115
|
|
108
116
|
@listeners << [str, io] if io
|
@@ -110,14 +118,12 @@ module Puma
|
|
110
118
|
path = "#{uri.host}#{uri.path}".gsub("%20", " ")
|
111
119
|
|
112
120
|
if fd = @inherited_fds.delete(str)
|
113
|
-
logger.log "* Inherited #{str}"
|
114
121
|
io = inherit_unix_listener path, fd
|
122
|
+
logger.log "* Inherited #{str}"
|
115
123
|
elsif sock = @activated_sockets.delete([ :unix, path ])
|
116
|
-
logger.log "* Activated #{str}"
|
117
124
|
io = inherit_unix_listener path, sock
|
125
|
+
logger.log "* Activated #{str}"
|
118
126
|
else
|
119
|
-
logger.log "* Listening on #{str}"
|
120
|
-
|
121
127
|
umask = nil
|
122
128
|
mode = nil
|
123
129
|
backlog = 1024
|
@@ -139,6 +145,7 @@ module Puma
|
|
139
145
|
end
|
140
146
|
|
141
147
|
io = add_unix_listener path, umask, mode, backlog
|
148
|
+
logger.log "* Listening on #{str}"
|
142
149
|
end
|
143
150
|
|
144
151
|
@listeners << [str, io]
|
@@ -162,6 +169,7 @@ module Puma
|
|
162
169
|
end
|
163
170
|
|
164
171
|
ctx.keystore_pass = params['keystore-pass']
|
172
|
+
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
|
165
173
|
else
|
166
174
|
unless params['key']
|
167
175
|
@events.error "Please specify the SSL key via 'key='"
|
@@ -182,8 +190,11 @@ module Puma
|
|
182
190
|
end
|
183
191
|
|
184
192
|
ctx.ca = params['ca'] if params['ca']
|
193
|
+
ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
|
185
194
|
end
|
186
195
|
|
196
|
+
ctx.no_tlsv1 = true if params['no_tlsv1'] == 'true'
|
197
|
+
|
187
198
|
if params['verify_mode']
|
188
199
|
ctx.verify_mode = case params['verify_mode']
|
189
200
|
when "peer"
|
@@ -202,11 +213,11 @@ module Puma
|
|
202
213
|
logger.log "* Inherited #{str}"
|
203
214
|
io = inherit_ssl_listener fd, ctx
|
204
215
|
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
|
205
|
-
logger.log "* Activated #{str}"
|
206
216
|
io = inherit_ssl_listener sock, ctx
|
217
|
+
logger.log "* Activated #{str}"
|
207
218
|
else
|
208
|
-
logger.log "* Listening on #{str}"
|
209
219
|
io = add_ssl_listener uri.host, uri.port, ctx
|
220
|
+
logger.log "* Listening on #{str}"
|
210
221
|
end
|
211
222
|
|
212
223
|
@listeners << [str, io] if io
|
@@ -313,6 +324,7 @@ module Puma
|
|
313
324
|
s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
314
325
|
s.listen backlog
|
315
326
|
|
327
|
+
|
316
328
|
ssl = MiniSSL::Server.new s, ctx
|
317
329
|
env = @proto_env.dup
|
318
330
|
env[HTTPS_KEY] = HTTPS
|
data/lib/puma/cli.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'optparse'
|
2
4
|
require 'uri'
|
3
5
|
|
6
|
+
require 'puma'
|
4
7
|
require 'puma/configuration'
|
5
8
|
require 'puma/launcher'
|
6
9
|
require 'puma/const'
|
@@ -83,6 +86,14 @@ module Puma
|
|
83
86
|
raise UnsupportedOption
|
84
87
|
end
|
85
88
|
|
89
|
+
def configure_control_url(command_line_arg)
|
90
|
+
if command_line_arg
|
91
|
+
@control_url = command_line_arg
|
92
|
+
elsif Puma.jruby?
|
93
|
+
unsupported "No default url available on JRuby"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
86
97
|
# Build the OptionParser object to handle the available options.
|
87
98
|
#
|
88
99
|
|
@@ -97,13 +108,13 @@ module Puma
|
|
97
108
|
file_config.load arg
|
98
109
|
end
|
99
110
|
|
100
|
-
o.on "--control URL", "The bind url to use for the control server"
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
111
|
+
o.on "--control-url URL", "The bind url to use for the control server. Use 'auto' to use temp unix server" do |arg|
|
112
|
+
configure_control_url(arg)
|
113
|
+
end
|
114
|
+
|
115
|
+
# alias --control-url for backwards-compatibility
|
116
|
+
o.on "--control URL", "DEPRECATED alias for --control-url" do |arg|
|
117
|
+
configure_control_url(arg)
|
107
118
|
end
|
108
119
|
|
109
120
|
o.on "--control-token TOKEN",
|
data/lib/puma/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class IO
|
2
4
|
# We need to use this for a jruby work around on both 1.8 and 1.9.
|
3
5
|
# So this either creates the constant (on 1.8), or harmlessly
|
@@ -21,6 +23,18 @@ module Puma
|
|
21
23
|
|
22
24
|
class ConnectionError < RuntimeError; end
|
23
25
|
|
26
|
+
# An instance of this class represents a unique request from a client.
|
27
|
+
# For example a web request from a browser or from CURL. This
|
28
|
+
#
|
29
|
+
# An instance of `Puma::Client` can be used as if it were an IO object
|
30
|
+
# by the reactor, that's because the latter is expected to call `#to_io`
|
31
|
+
# on any non-IO objects it polls. For example nio4r internally calls
|
32
|
+
# `IO::try_convert` (which may call `#to_io`) when a new socket is
|
33
|
+
# registered.
|
34
|
+
#
|
35
|
+
# Instances of this class are responsible for knowing if
|
36
|
+
# the header and body are fully buffered via the `try_to_finish` method.
|
37
|
+
# They can be used to "time out" a response via the `timeout_at` reader.
|
24
38
|
class Client
|
25
39
|
include Puma::Const
|
26
40
|
extend Puma::Delegation
|
@@ -41,6 +55,7 @@ module Puma
|
|
41
55
|
@ready = false
|
42
56
|
|
43
57
|
@body = nil
|
58
|
+
@body_read_start = nil
|
44
59
|
@buffer = nil
|
45
60
|
@tempfile = nil
|
46
61
|
|
@@ -51,6 +66,8 @@ module Puma
|
|
51
66
|
|
52
67
|
@peerip = nil
|
53
68
|
@remote_addr_header = nil
|
69
|
+
|
70
|
+
@body_remain = 0
|
54
71
|
end
|
55
72
|
|
56
73
|
attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked,
|
@@ -89,6 +106,8 @@ module Puma
|
|
89
106
|
@tempfile = nil
|
90
107
|
@parsed_bytes = 0
|
91
108
|
@ready = false
|
109
|
+
@body_remain = 0
|
110
|
+
@peerip = nil
|
92
111
|
|
93
112
|
if @buffer
|
94
113
|
@parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)
|
@@ -101,9 +120,16 @@ module Puma
|
|
101
120
|
end
|
102
121
|
|
103
122
|
return false
|
104
|
-
|
105
|
-
|
106
|
-
|
123
|
+
else
|
124
|
+
begin
|
125
|
+
if fast_check &&
|
126
|
+
IO.select([@to_io], nil, nil, FAST_TRACK_KA_TIMEOUT)
|
127
|
+
return try_to_finish
|
128
|
+
end
|
129
|
+
rescue IOError
|
130
|
+
# swallow it
|
131
|
+
end
|
132
|
+
|
107
133
|
end
|
108
134
|
end
|
109
135
|
|
@@ -134,8 +160,11 @@ module Puma
|
|
134
160
|
def decode_chunk(chunk)
|
135
161
|
if @partial_part_left > 0
|
136
162
|
if @partial_part_left <= chunk.size
|
137
|
-
|
163
|
+
if @partial_part_left > 2
|
164
|
+
@body << chunk[0..(@partial_part_left-3)] # skip the \r\n
|
165
|
+
end
|
138
166
|
chunk = chunk[@partial_part_left..-1]
|
167
|
+
@partial_part_left = 0
|
139
168
|
else
|
140
169
|
@body << chunk
|
141
170
|
@partial_part_left -= chunk.size
|
@@ -157,9 +186,9 @@ module Puma
|
|
157
186
|
if len == 0
|
158
187
|
@body.rewind
|
159
188
|
rest = io.read
|
189
|
+
rest = rest[2..-1] if rest.start_with?("\r\n")
|
160
190
|
@buffer = rest.empty? ? nil : rest
|
161
|
-
|
162
|
-
@ready = true
|
191
|
+
set_ready
|
163
192
|
return true
|
164
193
|
end
|
165
194
|
|
@@ -197,7 +226,7 @@ module Puma
|
|
197
226
|
while true
|
198
227
|
begin
|
199
228
|
chunk = @io.read_nonblock(4096)
|
200
|
-
rescue
|
229
|
+
rescue IO::WaitReadable
|
201
230
|
return false
|
202
231
|
rescue SystemCallError, IOError
|
203
232
|
raise ConnectionError, "Connection error detected during read"
|
@@ -207,8 +236,7 @@ module Puma
|
|
207
236
|
unless chunk
|
208
237
|
@body.close
|
209
238
|
@buffer = nil
|
210
|
-
|
211
|
-
@ready = true
|
239
|
+
set_ready
|
212
240
|
raise EOFError
|
213
241
|
end
|
214
242
|
|
@@ -217,6 +245,8 @@ module Puma
|
|
217
245
|
end
|
218
246
|
|
219
247
|
def setup_body
|
248
|
+
@body_read_start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
249
|
+
|
220
250
|
if @env[HTTP_EXPECT] == CONTINUE
|
221
251
|
# TODO allow a hook here to check the headers before
|
222
252
|
# going forward
|
@@ -241,8 +271,7 @@ module Puma
|
|
241
271
|
unless cl
|
242
272
|
@buffer = body.empty? ? nil : body
|
243
273
|
@body = EmptyBody
|
244
|
-
|
245
|
-
@ready = true
|
274
|
+
set_ready
|
246
275
|
return true
|
247
276
|
end
|
248
277
|
|
@@ -251,8 +280,7 @@ module Puma
|
|
251
280
|
if remain <= 0
|
252
281
|
@body = StringIO.new(body)
|
253
282
|
@buffer = nil
|
254
|
-
|
255
|
-
@ready = true
|
283
|
+
set_ready
|
256
284
|
return true
|
257
285
|
end
|
258
286
|
|
@@ -280,15 +308,14 @@ module Puma
|
|
280
308
|
data = @io.read_nonblock(CHUNK_SIZE)
|
281
309
|
rescue Errno::EAGAIN
|
282
310
|
return false
|
283
|
-
rescue SystemCallError, IOError
|
311
|
+
rescue SystemCallError, IOError, EOFError
|
284
312
|
raise ConnectionError, "Connection error detected during read"
|
285
313
|
end
|
286
314
|
|
287
315
|
# No data means a closed socket
|
288
316
|
unless data
|
289
317
|
@buffer = nil
|
290
|
-
|
291
|
-
@ready = true
|
318
|
+
set_ready
|
292
319
|
raise EOFError
|
293
320
|
end
|
294
321
|
|
@@ -324,8 +351,7 @@ module Puma
|
|
324
351
|
# No data means a closed socket
|
325
352
|
unless data
|
326
353
|
@buffer = nil
|
327
|
-
|
328
|
-
@ready = true
|
354
|
+
set_ready
|
329
355
|
raise EOFError
|
330
356
|
end
|
331
357
|
|
@@ -402,8 +428,7 @@ module Puma
|
|
402
428
|
unless chunk
|
403
429
|
@body.close
|
404
430
|
@buffer = nil
|
405
|
-
|
406
|
-
@ready = true
|
431
|
+
set_ready
|
407
432
|
raise EOFError
|
408
433
|
end
|
409
434
|
|
@@ -412,8 +437,7 @@ module Puma
|
|
412
437
|
if remain <= 0
|
413
438
|
@body.rewind
|
414
439
|
@buffer = nil
|
415
|
-
|
416
|
-
@ready = true
|
440
|
+
set_ready
|
417
441
|
return true
|
418
442
|
end
|
419
443
|
|
@@ -422,6 +446,14 @@ module Puma
|
|
422
446
|
false
|
423
447
|
end
|
424
448
|
|
449
|
+
def set_ready
|
450
|
+
if @body_read_start
|
451
|
+
@env['puma.request_body_wait'] = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - @body_read_start
|
452
|
+
end
|
453
|
+
@requests_served += 1
|
454
|
+
@ready = true
|
455
|
+
end
|
456
|
+
|
425
457
|
def write_400
|
426
458
|
begin
|
427
459
|
@io << ERROR_400_RESPONSE
|