Back to Blog

Ruby 2.6 adds write_timeout to Net::HTTP

on August 14, 2018
This blog is part of our Ruby 2.6 series.

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.

Example
1
2# server.rb
3
4require 'socket'
5
6server = TCPServer.new('localhost', 2345)
7loop do
8socket = server.accept
9end
10
Ruby 2.5.1
1
2# client.rb
3
4require 'net/http'
5
6connection = Net::HTTP.new('localhost', 2345)
7connection.open_timeout = 1
8connection.read_timeout = 3
9connection.start
10
11post = Net::HTTP::Post.new('/')
12body = (('a' _ 1023) + "\n") _ 5_000
13post.body = body
14
15puts "Sending #{body.bytesize} bytes"
16connection.request(post)
17
Output
1\$ RBENV_VERSION=2.5.1 ruby client.rb
2
3Sending 5120000 bytes

Ruby 2.5.1 processes request endlessly unless above program is interrupted.

Ruby 2.6.0-dev

Add write_timeout attribute to Net::HTTP instance in client.rb program.

1
2# client.rb
3
4require 'net/http'
5
6connection = Net::HTTP.new('localhost', 2345)
7connection.open_timeout = 1
8connection.read_timeout = 3
9
10# set write_timeout to 10 seconds
11
12connection.write_timeout = 10
13
14connection.start
15
16post = Net::HTTP::Post.new('/')
17body = (('a' _ 1023) + "\n") _ 5_000
18post.body = body
19
20puts "Sending #{body.bytesize} bytes"
21connection.request(post)
22
Output
1\$ RBENV_VERSION=2.6.0-dev ruby client.rb
2
3Sending 5120000 bytes
4Traceback (most recent call last):
513: `from client.rb:17:in `<main>`` 12: `from /net/http.rb:1479:in `request``
611: `from /net/http.rb:1506:in `transport_request`` 10: `from /net/http.rb:1506:in `catch``
79: `from /net/http.rb:1507:in `block in transport_request`` 8: `from /net/http/generic_request.rb:123:in `exec``
87: `from /net/http/generic_request.rb:189:in `send_request_with_body`` 6: `from /net/protocol.rb:221:in `write``
95: `from /net/protocol.rb:239:in `writing`` 4: `from /net/protocol.rb:222:in `block in write``
103: `from /net/protocol.rb:249:in `write0`` 2: `from /net/protocol.rb:249:in `each_with_index``
111: `from /net/protocol.rb:249:in `each`` `/net/protocol.rb:270:in `block in write0`: Net::WriteTimeout (Net::WriteTimeout)`
12

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.


You might also like

If you liked this blog post, check out similar ones from BigBinary