Merge branch 'handle-long-uploads' of git://github.com/weknowtraining/puma into weknowtraining-handle-long-uploads
This commit is contained in:
commit
3670ea1db6
|
@ -206,8 +206,9 @@ module Puma
|
|||
try_to_finish
|
||||
end
|
||||
|
||||
def finish(timeout)
|
||||
def finish(first_data_timeout, between_bytes_timeout)
|
||||
return if @ready
|
||||
timeout = @parsed_bytes > 0 ? between_bytes_timeout : first_data_timeout
|
||||
IO.select([@to_io], nil, nil, timeout) || timeout! until try_to_finish
|
||||
end
|
||||
|
||||
|
|
|
@ -272,6 +272,12 @@ module Puma
|
|||
@options[:first_data_timeout] = Integer(seconds)
|
||||
end
|
||||
|
||||
# Define how long the tcp socket stays open, once data has been received.
|
||||
# @see Puma::Server.new
|
||||
def between_bytes_timeout(seconds)
|
||||
@options[:between_bytes_timeout] = Integer(seconds)
|
||||
end
|
||||
|
||||
# Work around leaky apps that leave garbage in Thread locals
|
||||
# across requests.
|
||||
def clean_thread_locals(which=true)
|
||||
|
|
|
@ -40,12 +40,14 @@ module Puma
|
|||
attr_reader :requests_count # @version 5.0.0
|
||||
|
||||
# @todo the following may be deprecated in the future
|
||||
attr_reader :auto_trim_time, :early_hints, :first_data_timeout,
|
||||
attr_reader :auto_trim_time, :early_hints,
|
||||
:first_data_timeout, :between_bytes_timeout,
|
||||
:leak_stack_on_error,
|
||||
:persistent_timeout, :reaping_time
|
||||
|
||||
# @deprecated v6.0.0
|
||||
attr_writer :auto_trim_time, :early_hints, :first_data_timeout,
|
||||
attr_writer :auto_trim_time, :early_hints,
|
||||
:first_data_timeout, :between_bytes_timeout,
|
||||
:leak_stack_on_error, :min_threads, :max_threads,
|
||||
:persistent_timeout, :reaping_time
|
||||
|
||||
|
@ -84,14 +86,15 @@ module Puma
|
|||
|
||||
@options = options
|
||||
|
||||
@early_hints = options.fetch :early_hints, nil
|
||||
@first_data_timeout = options.fetch :first_data_timeout, FIRST_DATA_TIMEOUT
|
||||
@min_threads = options.fetch :min_threads, 0
|
||||
@max_threads = options.fetch :max_threads , (Puma.mri? ? 5 : 16)
|
||||
@persistent_timeout = options.fetch :persistent_timeout, PERSISTENT_TIMEOUT
|
||||
@queue_requests = options.fetch :queue_requests, true
|
||||
@max_fast_inline = options.fetch :max_fast_inline, MAX_FAST_INLINE
|
||||
@io_selector_backend = options.fetch :io_selector_backend, :auto
|
||||
@early_hints = options.fetch :early_hints, nil
|
||||
@first_data_timeout = options.fetch :first_data_timeout, FIRST_DATA_TIMEOUT
|
||||
@between_bytes_timeout = options.fetch :between_bytes_timeout, @first_data_timeout
|
||||
@min_threads = options.fetch :min_threads, 0
|
||||
@max_threads = options.fetch :max_threads , (Puma.mri? ? 5 : 16)
|
||||
@persistent_timeout = options.fetch :persistent_timeout, PERSISTENT_TIMEOUT
|
||||
@queue_requests = options.fetch :queue_requests, true
|
||||
@max_fast_inline = options.fetch :max_fast_inline, MAX_FAST_INLINE
|
||||
@io_selector_backend = options.fetch :io_selector_backend, :auto
|
||||
|
||||
temp = !!(@options[:environment] =~ /\A(development|test)\z/)
|
||||
@leak_stack_on_error = @options[:environment] ? temp : true
|
||||
|
@ -296,7 +299,7 @@ module Puma
|
|||
elsif shutdown || client.timeout == 0
|
||||
client.timeout!
|
||||
else
|
||||
client.set_timeout(@first_data_timeout)
|
||||
client.set_timeout(@between_bytes_timeout)
|
||||
false
|
||||
end
|
||||
rescue StandardError => e
|
||||
|
@ -430,7 +433,7 @@ module Puma
|
|||
end
|
||||
|
||||
with_force_shutdown(client) do
|
||||
client.finish(@first_data_timeout)
|
||||
client.finish(@first_data_timeout, @between_bytes_timeout)
|
||||
end
|
||||
|
||||
while true
|
||||
|
|
|
@ -436,24 +436,24 @@ EOF
|
|||
assert_equal [:booting, :running, :stop, :done], states
|
||||
end
|
||||
|
||||
def test_timeout_in_data_phase(**options)
|
||||
server_run(first_data_timeout: 1, **options)
|
||||
def test_timeout_in_data_phase
|
||||
@server.first_data_timeout = 2
|
||||
server_run
|
||||
|
||||
sock = send_http "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\n"
|
||||
|
||||
sock << "Hello" unless IO.select([sock], nil, nil, 1.15)
|
||||
|
||||
data = sock.gets
|
||||
data = assert_proper_timeout(@server.first_data_timeout) { sock.gets }
|
||||
|
||||
assert_equal "HTTP/1.1 408 Request Timeout\r\n", data
|
||||
end
|
||||
|
||||
def test_timeout_data_no_queue
|
||||
@server = Puma::Server.new @app, @events, queue_requests: false
|
||||
test_timeout_in_data_phase(queue_requests: false)
|
||||
end
|
||||
|
||||
# https://github.com/puma/puma/issues/2574
|
||||
def test_no_timeout_after_data_received
|
||||
def test_no_timeout_after_data_received_first_data
|
||||
@server.first_data_timeout = 1
|
||||
server_run
|
||||
|
||||
|
@ -476,6 +476,44 @@ EOF
|
|||
test_no_timeout_after_data_received
|
||||
end
|
||||
|
||||
def test_timeout_after_data_received
|
||||
@server.first_data_timeout = 4
|
||||
@server.between_bytes_timeout = 2
|
||||
server_run
|
||||
|
||||
sock = send_http "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 100\r\n\r\n"
|
||||
sleep 0.1
|
||||
|
||||
sock << "hello"
|
||||
sleep 0.1
|
||||
|
||||
data = assert_proper_timeout(@server.between_bytes_timeout) { sock.gets }
|
||||
|
||||
assert_equal "HTTP/1.1 408 Request Timeout\r\n", data
|
||||
end
|
||||
|
||||
def test_timeout_after_data_received_no_queue
|
||||
@server = Puma::Server.new @app, @events, queue_requests: false
|
||||
test_timeout_after_data_received
|
||||
end
|
||||
|
||||
def test_no_timeout_after_data_received
|
||||
@server.first_data_timeout = 10
|
||||
@server.between_bytes_timeout = 4
|
||||
server_run
|
||||
|
||||
sock = send_http "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 10\r\n\r\n"
|
||||
sleep 0.1
|
||||
|
||||
sock << "hello"
|
||||
sleep 2
|
||||
sock << "world"
|
||||
|
||||
data = sock.gets
|
||||
|
||||
assert_equal "HTTP/1.1 200 OK\r\n", data
|
||||
end
|
||||
|
||||
def test_http_11_keep_alive_with_body
|
||||
server_run { [200, {"Content-Type" => "plain/text"}, ["hello\n"]] }
|
||||
|
||||
|
@ -1331,4 +1369,14 @@ EOF
|
|||
data = send_http_and_read "GET / HTTP/1.0\r\n\r\n"
|
||||
assert_equal "user", data.split("\r\n").last
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_proper_timeout(expected)
|
||||
now = Time.now
|
||||
ret = yield
|
||||
t = Time.now - now
|
||||
assert_in_delta expected, t, 0.5, "unexpected timeout, #{t} instead of ~#{expected}"
|
||||
ret
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue