Skip to content

Commit a0fab1a

Browse files
miguelfteixeirajeremyevans
authored andcommitted
Enforce write timeout when body_stream is used
The existing implementation of `Net::HTTP#write_timeout` relies on `Net::BefferedIO` to trigger the `Net::WriteTimeout` error. This commit changes `send_request_with_body_stream` to remove the optimization that was making `Net::HTTP#write_timeout` not work when `body_stream` is used. Open issue: https://bugs.ruby-lang.org/issues/17933
1 parent 5f02f5d commit a0fab1a

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

lib/net/http/generic_request.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,7 @@ def send_request_with_body_stream(sock, ver, path, f)
202202
IO.copy_stream(f, chunker)
203203
chunker.finish
204204
else
205-
# copy_stream can sendfile() to sock.io unless we use SSL.
206-
# If sock.io is an SSLSocket, copy_stream will hit SSL_write()
207-
IO.copy_stream(f, sock.io)
205+
IO.copy_stream(f, sock)
208206
end
209207
end
210208

test/net/http/test_http.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,34 @@ def test_timeout_during_HTTP_session_write
576576
th&.join
577577
end
578578

579+
def test_timeout_during_non_chunked_streamed_HTTP_session_write
580+
th = nil
581+
# listen for connections... but deliberately do not read
582+
TCPServer.open('localhost', 0) {|server|
583+
port = server.addr[1]
584+
585+
conn = Net::HTTP.new('localhost', port)
586+
conn.write_timeout = 0.01
587+
conn.read_timeout = 0.01 if windows?
588+
conn.open_timeout = 0.1
589+
590+
req = Net::HTTP::Post.new('/')
591+
data = "a"*50_000_000
592+
req.content_length = data.size
593+
req['Content-Type'] = 'application/x-www-form-urlencoded'
594+
req.body_stream = StringIO.new(data)
595+
596+
th = Thread.new do
597+
err = !windows? ? Net::WriteTimeout : Net::ReadTimeout
598+
assert_raise(err) { conn.request(req) }
599+
end
600+
assert th.join(10)
601+
}
602+
ensure
603+
th&.kill
604+
th&.join
605+
end
606+
579607
def test_timeout_during_HTTP_session
580608
bug4246 = "expected the HTTP session to have timed out but have not. c.f. [ruby-core:34203]"
581609

0 commit comments

Comments
 (0)