From 515a669a06d2b654b4602441f5b6b0fe00085247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20H=C3=B6rberg?= Date: Tue, 19 Jan 2021 10:44:36 +0100 Subject: [PATCH] Net::HTTP#resolv_timeout and TCP connect_timeout Based on https://bugs.ruby-lang.org/issues/16381 but rerasing Errno::ETIMEDOUT as Net::OpenTimeout --- lib/net/http.rb | 12 +++++++--- .../net/http/http/resolv_timeout_spec.rb | 24 +++++++++++++++++++ spec/ruby/library/socket/socket/tcp_spec.rb | 6 +++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 spec/ruby/library/net/http/http/resolv_timeout_spec.rb diff --git a/lib/net/http.rb b/lib/net/http.rb index 86fca183c1c024..e208bf54c1e384 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -760,6 +760,11 @@ def ipaddr=(addr) # Net::OpenTimeout exception. The default value is 60 seconds. attr_accessor :open_timeout + # Specify the DNS name resolution timeout in seconds. If the name + # cannot be resolved in this many seconds, it raises a + # SocketError exception. The default value is set by operation system. + attr_accessor :resolv_timeout + # Number of seconds to wait for one block to be read (via one read(2) # call). Any number may be used, including Floats for fractional # seconds. If the HTTP object cannot read data in this many seconds, @@ -981,14 +986,15 @@ def connect end D "opening connection to #{conn_addr}:#{conn_port}..." - s = Timeout.timeout(@open_timeout, Net::OpenTimeout) { + s = begin - TCPSocket.open(conn_addr, conn_port, @local_host, @local_port) + Socket.tcp(conn_address, conn_port, @local_host, @local_port, connect_timeout: @open_timeout, resolv_timeout: @resolv_timeout) + rescue Errno::ETIMEDOUT + raise Net::OpenTimeout rescue => e raise e, "Failed to open TCP connection to " + "#{conn_addr}:#{conn_port} (#{e.message})" end - } s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) D "opened" if use_ssl? diff --git a/spec/ruby/library/net/http/http/resolv_timeout_spec.rb b/spec/ruby/library/net/http/http/resolv_timeout_spec.rb new file mode 100644 index 00000000000000..7817bb00c12048 --- /dev/null +++ b/spec/ruby/library/net/http/http/resolv_timeout_spec.rb @@ -0,0 +1,24 @@ +require_relative '../../../../spec_helper' +require 'net/http' + +describe "Net::HTTP#resolv_timeout" do + it "returns the seconds to wait until reading one block" do + net = Net::HTTP.new("localhost") + net.resolv_timeout.should eql(nil) + net.resolv_timeout = 10 + net.resolv_timeout.should eql(10) + end +end + +describe "Net::HTTP#resolv_timeout=" do + it "sets the seconds to wait till the connection is open" do + net = Net::HTTP.new("localhost") + net.resolv_timeout = 10 + net.resolv_timeout.should eql(10) + end + + it "returns the newly set value" do + net = Net::HTTP.new("localhost") + (net.resolv_timeout = 10).should eql(10) + end +end diff --git a/spec/ruby/library/socket/socket/tcp_spec.rb b/spec/ruby/library/socket/socket/tcp_spec.rb index faf020b1ead615..67ccba0512956b 100644 --- a/spec/ruby/library/socket/socket/tcp_spec.rb +++ b/spec/ruby/library/socket/socket/tcp_spec.rb @@ -67,4 +67,10 @@ connection.close end end + + it 'accepts tcp timeout' do + @client = Socket.tcp(@host, @port, resolv_timeout: 1) + @client.write('hello') + @client.close + end end