We write about Ruby on Rails, React.js, React Native, remote work, open source, engineering and design.
Ruby 2.6.0 was released on Dec 25, 2018.
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.