August 14, 2018
This blog is part of our Ruby 2.6 series.
Before Ruby 2.6, if we created a large request with Net::HTTP
, it would hang
forever until request is interrupted. To fix this issue,
write_timeout
attribute and
write_timeout=
method is added to Net::HTTP in Ruby
2.6. Default value for write_timeout
is 60 seconds and can be set to an
integer or a float value.
Similarly, write_timeout
attribute and write_timeout=
method is added to
Net::BufferedIO
class.
If any chunk of response is not written within number of seconds provided to
write_timeout
, Net::WriteTimeout
exception is raised. Net::WriteTimeout
exception is not raised on Windows
systems.
# server.rb
require 'socket'
server = TCPServer.new('localhost', 2345)
loop do
socket = server.accept
end
# client.rb
require 'net/http'
connection = Net::HTTP.new('localhost', 2345)
connection.open_timeout = 1
connection.read_timeout = 3
connection.start
post = Net::HTTP::Post.new('/')
body = (('a' _ 1023) + "\n") _ 5_000
post.body = body
puts "Sending #{body.bytesize} bytes"
connection.request(post)
\$ RBENV_VERSION=2.5.1 ruby client.rb
Sending 5120000 bytes
Ruby 2.5.1 processes request endlessly unless above program is interrupted.
Add write_timeout
attribute to Net::HTTP
instance in client.rb program.
# client.rb
require 'net/http'
connection = Net::HTTP.new('localhost', 2345)
connection.open_timeout = 1
connection.read_timeout = 3
# set write_timeout to 10 seconds
connection.write_timeout = 10
connection.start
post = Net::HTTP::Post.new('/')
body = (('a' _ 1023) + "\n") _ 5_000
post.body = body
puts "Sending #{body.bytesize} bytes"
connection.request(post)
\$ RBENV_VERSION=2.6.0-dev ruby client.rb
Sending 5120000 bytes
Traceback (most recent call last):
13: `from client.rb:17:in `<main>`` 12: `from /net/http.rb:1479:in `request``
11: `from /net/http.rb:1506:in `transport_request`` 10: `from /net/http.rb:1506:in `catch``
9: `from /net/http.rb:1507:in `block in transport_request`` 8: `from /net/http/generic_request.rb:123:in `exec``
7: `from /net/http/generic_request.rb:189:in `send_request_with_body`` 6: `from /net/protocol.rb:221:in `write``
5: `from /net/protocol.rb:239:in `writing`` 4: `from /net/protocol.rb:222:in `block in write``
3: `from /net/protocol.rb:249:in `write0`` 2: `from /net/protocol.rb:249:in `each_with_index``
1: `from /net/protocol.rb:249:in `each`` `/net/protocol.rb:270:in `block in write0`: Net::WriteTimeout (Net::WriteTimeout)`
In Ruby 2.6.0, above program is terminated raising Net::WriteTimeout
exception
after 10 seconds (value set to write_timeout
attribute).
Here is relevant commit and discussion for this change.
If this blog was helpful, check out our full blog archive.