Ruby 2.6 adds write_timeout to Net::HTTP

Taha Husain

Taha Husain

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.

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.

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.