From 9074c332fe9ac63979c41659fbecf1e226f9bf8e Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 17:34:21 +0500 Subject: [PATCH 01/21] Add integration test for net_http + read_timeout --- spec/integration/net_http_spec.rb | 9 +++++++++ spec/integration/support/application.rb | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/spec/integration/net_http_spec.rb b/spec/integration/net_http_spec.rb index fcee178..ee722d4 100644 --- a/spec/integration/net_http_spec.rb +++ b/spec/integration/net_http_spec.rb @@ -30,6 +30,15 @@ expect(response.headers["Set-Cookie"]).to eq(cookies) end + it "it supports read timeout" do + request = HTTPI::Request.new(@server.url + "timeout") + request.read_timeout = 0.5 # seconds + + expect do + HTTPI.get(request, adapter) + end.to raise_exception(Net::ReadTimeout) + end + it "executes GET requests" do response = HTTPI.get(@server.url, adapter) expect(response.body).to eq("get") diff --git a/spec/integration/support/application.rb b/spec/integration/support/application.rb index 20c9bc4..0f6d26c 100644 --- a/spec/integration/support/application.rb +++ b/spec/integration/support/application.rb @@ -15,9 +15,10 @@ def self.respond_with(body) } end - map "/repeat" do + map "/timeout" do run lambda { |env| - IntegrationServer.respond_with :body => env["rack.input"].read + sleep 2 + IntegrationServer.respond_with "done" } end From 8b249bcaec4ed8f771665f02e84d9a1f7c785a6d Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 17:43:15 +0500 Subject: [PATCH 02/21] Add integration test for net_http_persistent + read_timeout --- spec/integration/net_http_persistent_spec.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/spec/integration/net_http_persistent_spec.rb b/spec/integration/net_http_persistent_spec.rb index 28aabbf..cf4ff47 100644 --- a/spec/integration/net_http_persistent_spec.rb +++ b/spec/integration/net_http_persistent_spec.rb @@ -30,6 +30,17 @@ expect(response.headers["Set-Cookie"]).to eq(cookies) end + it "it supports read timeout" do + require "net/http/persistent" + + request = HTTPI::Request.new(@server.url + "timeout") + request.read_timeout = 0.5 # seconds + + expect do + HTTPI.get(request, adapter) + end.to raise_exception(Net::HTTP::Persistent::Error, /Net::ReadTimeout/) + end + it "executes GET requests" do response = HTTPI.get(@server.url, adapter) expect(response.body).to eq("get") @@ -38,7 +49,7 @@ it "executes POST requests" do request = HTTPI::Request.new(url: @server.url, open_timeout: 1, read_timeout: 1, body: "xml") - + response = HTTPI.post(request, adapter) expect(response.body).to eq("post") expect(response.headers["Content-Type"]).to eq("text/plain") From f692635dcb04b9bdac22a0c6b2cc096de6703b4a Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 18:30:49 +0500 Subject: [PATCH 03/21] Add integration test for excon + read_timeout --- spec/integration/excon_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/integration/excon_spec.rb b/spec/integration/excon_spec.rb index ed45b58..31ad00b 100644 --- a/spec/integration/excon_spec.rb +++ b/spec/integration/excon_spec.rb @@ -30,6 +30,17 @@ expect(response.headers["Set-Cookie"]).to eq(cookies) end + it "it supports read timeout" do + require "excon" + + request = HTTPI::Request.new(@server.url + "timeout") + request.read_timeout = 0.5 # seconds + + expect do + HTTPI.get(request, adapter) + end.to raise_exception(Excon::Error::Timeout) + end + it "executes GET requests" do response = HTTPI.get(@server.url, adapter) expect(response.body).to eq("get") From 6046d35c33ceee4167d8c23b532beae045fda6d2 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 18:31:50 +0500 Subject: [PATCH 04/21] Set timeouts in msec in curb adapter Why: for better support of the floating point values in `read_timeout` and `open_timeout` options. --- lib/httpi/adapter/curb.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/httpi/adapter/curb.rb b/lib/httpi/adapter/curb.rb index f6afb41..bfe55a6 100644 --- a/lib/httpi/adapter/curb.rb +++ b/lib/httpi/adapter/curb.rb @@ -72,8 +72,8 @@ def setup_client def basic_setup @client.url = @request.url.to_s @client.proxy_url = @request.proxy.to_s if @request.proxy - @client.timeout = @request.read_timeout if @request.read_timeout - @client.connect_timeout = @request.open_timeout if @request.open_timeout + @client.timeout_ms = @request.read_timeout * 1000 if @request.read_timeout + @client.connect_timeout_ms = @request.open_timeout * 1000 if @request.open_timeout @client.headers = @request.headers.to_hash @client.verbose = false # cURL workaround From bf760e1274f962e129dd98f11508c8207da9c43e Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 18:34:09 +0500 Subject: [PATCH 05/21] Add integration test for curb + read_timeout --- spec/integration/curb_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/integration/curb_spec.rb b/spec/integration/curb_spec.rb index a13af0f..912d995 100644 --- a/spec/integration/curb_spec.rb +++ b/spec/integration/curb_spec.rb @@ -33,6 +33,17 @@ expect(response.headers["Set-Cookie"]).to eq(cookies) end + it "it supports read timeout" do + require "curb" + + request = HTTPI::Request.new(@server.url + "timeout") + request.read_timeout = 0.5 # seconds + + expect do + puts HTTPI.get(request, adapter).inspect + end.to raise_exception(Curl::Err::TimeoutError) + end + it "executes GET requests" do response = HTTPI.get(@server.url, adapter) expect(response.body).to eq("get") From 4544e6cee5efe4ad20dfe706d76f5f5be77e46ee Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 18:38:50 +0500 Subject: [PATCH 06/21] Add integration test for em_http + read_timeout --- spec/integration/em_http_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/spec/integration/em_http_spec.rb b/spec/integration/em_http_spec.rb index e980b1e..259b86d 100644 --- a/spec/integration/em_http_spec.rb +++ b/spec/integration/em_http_spec.rb @@ -42,6 +42,15 @@ expect(response.headers["Set-Cookie"]).to eq(cookies) end + it "it supports read timeout" do + request = HTTPI::Request.new(@server.url + "timeout") + request.read_timeout = 0.5 # seconds + + expect do + puts HTTPI.get(request, adapter).inspect + end.to raise_exception(HTTPI::TimeoutError) + end + it "executes GET requests" do response = HTTPI.get(@server.url, adapter) expect(response.body).to eq("get") From ec837d20bab001cd8d64250f3a0d8d29322465a5 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 18:42:04 +0500 Subject: [PATCH 07/21] Add integration test for httpclient + read_timeout --- spec/integration/httpclient_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/integration/httpclient_spec.rb b/spec/integration/httpclient_spec.rb index 934a060..a699ee6 100644 --- a/spec/integration/httpclient_spec.rb +++ b/spec/integration/httpclient_spec.rb @@ -30,6 +30,17 @@ expect(response.headers["Set-Cookie"]).to eq(cookies) end + it "it supports read timeout" do + require "httpclient" + + request = HTTPI::Request.new(@server.url + "timeout") + request.read_timeout = 0.5 # seconds + + expect do + puts HTTPI.get(request, adapter).inspect + end.to raise_exception(HTTPClient::ReceiveTimeoutError) + end + it "executes GET requests" do response = HTTPI.get(@server.url, adapter) expect(response.body).to eq("get") From 370e3f5e184ecab3ec6f04e7633d479eb28e0223 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 19:03:38 +0500 Subject: [PATCH 08/21] Add support for open/read timeouts to http adapter --- lib/httpi/adapter/http.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/httpi/adapter/http.rb b/lib/httpi/adapter/http.rb index e60e787..35366c9 100644 --- a/lib/httpi/adapter/http.rb +++ b/lib/httpi/adapter/http.rb @@ -73,6 +73,11 @@ def create_client client = client.via(@request.proxy.host, @request.proxy.port, @request.proxy.user, @request.proxy.password) end + timeouts = {} + timeouts[:connect] = @request.open_timeout if @request.open_timeout + timeouts[:read] = @request.read_timeout if @request.read_timeout + client = client.timeout(timeouts) if timeouts.any? + client.headers(@request.headers) end end From b8426ac1d020d65eeaa476ebc41467af8e1bade5 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 19:04:01 +0500 Subject: [PATCH 09/21] Add integration test for http + read_timeout --- spec/integration/http_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/integration/http_spec.rb b/spec/integration/http_spec.rb index 5f167d3..e65cd1a 100644 --- a/spec/integration/http_spec.rb +++ b/spec/integration/http_spec.rb @@ -30,6 +30,18 @@ expect(response.headers["Set-Cookie"]).to eq(cookies) end + it "it supports read timeout" do + require "http" + + request = HTTPI::Request.new(@server.url + "timeout") + request.read_timeout = 0.5 # seconds + + expect do + HTTPI.get(request, adapter) + end.to raise_exception(HTTP::TimeoutError) + end + + it "executes GET requests" do response = HTTPI.get(@server.url, adapter) expect(response.body).to eq("get") From 06d20863c4f39f28360e30347c4b93828b41d519 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 19:05:16 +0500 Subject: [PATCH 10/21] Remove debug output from timeout specs --- spec/integration/curb_spec.rb | 2 +- spec/integration/em_http_spec.rb | 2 +- spec/integration/httpclient_spec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/integration/curb_spec.rb b/spec/integration/curb_spec.rb index 912d995..598a82a 100644 --- a/spec/integration/curb_spec.rb +++ b/spec/integration/curb_spec.rb @@ -40,7 +40,7 @@ request.read_timeout = 0.5 # seconds expect do - puts HTTPI.get(request, adapter).inspect + HTTPI.get(request, adapter) end.to raise_exception(Curl::Err::TimeoutError) end diff --git a/spec/integration/em_http_spec.rb b/spec/integration/em_http_spec.rb index 259b86d..fb04bdf 100644 --- a/spec/integration/em_http_spec.rb +++ b/spec/integration/em_http_spec.rb @@ -47,7 +47,7 @@ request.read_timeout = 0.5 # seconds expect do - puts HTTPI.get(request, adapter).inspect + HTTPI.get(request, adapter) end.to raise_exception(HTTPI::TimeoutError) end diff --git a/spec/integration/httpclient_spec.rb b/spec/integration/httpclient_spec.rb index a699ee6..be52cb8 100644 --- a/spec/integration/httpclient_spec.rb +++ b/spec/integration/httpclient_spec.rb @@ -37,7 +37,7 @@ request.read_timeout = 0.5 # seconds expect do - puts HTTPI.get(request, adapter).inspect + HTTPI.get(request, adapter) end.to raise_exception(HTTPClient::ReceiveTimeoutError) end From c59e11a1aa638f81e69dbbd1e7bbd8408a06fad8 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 19:16:13 +0500 Subject: [PATCH 11/21] Fix broken timeout specs for curb adapter --- spec/httpi/adapter/curb_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/httpi/adapter/curb_spec.rb b/spec/httpi/adapter/curb_spec.rb index b624447..2c670e7 100644 --- a/spec/httpi/adapter/curb_spec.rb +++ b/spec/httpi/adapter/curb_spec.rb @@ -146,29 +146,29 @@ end end - describe "timeout" do + describe "timeout_ms" do it "is not set unless it's specified" do - curb.expects(:timeout=).never + curb.expects(:timeout_ms=).never adapter.request(:get) end it "is set if specified" do request.read_timeout = 30 - curb.expects(:timeout=).with(request.read_timeout) + curb.expects(:timeout_ms=).with(30_000) adapter.request(:get) end end - describe "connect_timeout" do + describe "connect_timeout_ms" do it "is not set unless it's specified" do - curb.expects(:connect_timeout=).never + curb.expects(:connect_timeout_ms=).never adapter.request(:get) end it "is set if specified" do request.open_timeout = 30 - curb.expects(:connect_timeout=).with(30) + curb.expects(:connect_timeout_ms=).with(30_000) adapter.request(:get) end From 1c3aba498e9cbd1ccaeee54770b973ad74686181 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 20:43:57 +0500 Subject: [PATCH 12/21] Fix em_http adapter: do not set timeouts to nil explicitly --- lib/httpi/adapter/em_http.rb | 8 ++++---- spec/httpi/adapter/em_http_spec.rb | 21 +++++++++------------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/lib/httpi/adapter/em_http.rb b/lib/httpi/adapter/em_http.rb index 3aeb58d..104e031 100644 --- a/lib/httpi/adapter/em_http.rb +++ b/lib/httpi/adapter/em_http.rb @@ -69,10 +69,10 @@ def _request end def connection_options - options = { - :connect_timeout => @request.open_timeout, - :inactivity_timeout => @request.read_timeout - } + options = {} + + options[:inactivity_timeout] = @request.read_timeout if @request.read_timeout + options[:connect_timeout] = @request.open_timeout if @request.open_timeout options[:proxy] = proxy_options if @request.proxy diff --git a/spec/httpi/adapter/em_http_spec.rb b/spec/httpi/adapter/em_http_spec.rb index a171138..4b82452 100644 --- a/spec/httpi/adapter/em_http_spec.rb +++ b/spec/httpi/adapter/em_http_spec.rb @@ -89,15 +89,12 @@ end it "sets host, port and authorization" do - url = 'http://example.com:80' - + url = "http://example.com:80" connection_options = { - :connect_timeout => nil, - :inactivity_timeout => nil, - :proxy => { - :host => 'proxy-host.com', - :port => 443, - :authorization => ['username', 'password'] + :proxy => { + :host => "proxy-host.com", + :port => 443, + :authorization => ["username", "password"] } } @@ -111,8 +108,8 @@ it "is passed as a connection option" do request.open_timeout = 30 - url = 'http://example.com:80' - connection_options = { :connect_timeout => 30, :inactivity_timeout => nil } + url = "http://example.com:80" + connection_options = { connect_timeout: 30 } EventMachine::HttpRequest.expects(:new).with(url, connection_options) @@ -124,8 +121,8 @@ it "is passed as a connection option" do request.read_timeout = 60 - url = 'http://example.com:80' - connection_options = { :connect_timeout => nil, :inactivity_timeout => 60 } + url = "http://example.com:80" + connection_options = { inactivity_timeout: 60 } EventMachine::HttpRequest.expects(:new).with(url, connection_options) From f9c326c94617ce95893dc58933d04ea32d88fc1e Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 20:48:43 +0500 Subject: [PATCH 13/21] Add support for write_timeout config option --- lib/httpi/adapter/curb.rb | 3 ++- lib/httpi/adapter/em_http.rb | 3 ++- lib/httpi/adapter/excon.rb | 1 + lib/httpi/adapter/http.rb | 1 + lib/httpi/adapter/httpclient.rb | 1 + lib/httpi/adapter/net_http.rb | 7 +++++++ lib/httpi/adapter/net_http_persistent.rb | 1 + lib/httpi/request.rb | 4 ++-- 8 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/httpi/adapter/curb.rb b/lib/httpi/adapter/curb.rb index bfe55a6..99fc3b0 100644 --- a/lib/httpi/adapter/curb.rb +++ b/lib/httpi/adapter/curb.rb @@ -72,7 +72,8 @@ def setup_client def basic_setup @client.url = @request.url.to_s @client.proxy_url = @request.proxy.to_s if @request.proxy - @client.timeout_ms = @request.read_timeout * 1000 if @request.read_timeout + read_or_write_timeout = @request.read_timeout || @request.write_timeout + @client.timeout_ms = read_or_write_timeout * 1000 if read_or_write_timeout @client.connect_timeout_ms = @request.open_timeout * 1000 if @request.open_timeout @client.headers = @request.headers.to_hash @client.verbose = false diff --git a/lib/httpi/adapter/em_http.rb b/lib/httpi/adapter/em_http.rb index 104e031..412bbf3 100644 --- a/lib/httpi/adapter/em_http.rb +++ b/lib/httpi/adapter/em_http.rb @@ -71,7 +71,8 @@ def _request def connection_options options = {} - options[:inactivity_timeout] = @request.read_timeout if @request.read_timeout + read_or_write_timeout = @request.read_timeout || @request.write_timeout + options[:inactivity_timeout] = read_or_write_timeout if read_or_write_timeout options[:connect_timeout] = @request.open_timeout if @request.open_timeout options[:proxy] = proxy_options if @request.proxy diff --git a/lib/httpi/adapter/excon.rb b/lib/httpi/adapter/excon.rb index b80396b..a03cd8f 100644 --- a/lib/httpi/adapter/excon.rb +++ b/lib/httpi/adapter/excon.rb @@ -58,6 +58,7 @@ def client_opts opts[:user], opts[:password] = *@request.auth.credentials if @request.auth.basic? opts[:connect_timeout] = @request.open_timeout if @request.open_timeout opts[:read_timeout] = @request.read_timeout if @request.read_timeout + opts[:write_timeout] = @request.write_timeout if @request.write_timeout opts[:response_block] = @request.on_body if @request.on_body opts[:proxy] = @request.proxy if @request.proxy diff --git a/lib/httpi/adapter/http.rb b/lib/httpi/adapter/http.rb index 35366c9..8b702c0 100644 --- a/lib/httpi/adapter/http.rb +++ b/lib/httpi/adapter/http.rb @@ -76,6 +76,7 @@ def create_client timeouts = {} timeouts[:connect] = @request.open_timeout if @request.open_timeout timeouts[:read] = @request.read_timeout if @request.read_timeout + timeouts[:write] = @request.write_timeout if @request.write_timeout client = client.timeout(timeouts) if timeouts.any? client.headers(@request.headers) diff --git a/lib/httpi/adapter/httpclient.rb b/lib/httpi/adapter/httpclient.rb index 97cd56b..9165805 100644 --- a/lib/httpi/adapter/httpclient.rb +++ b/lib/httpi/adapter/httpclient.rb @@ -45,6 +45,7 @@ def basic_setup @client.proxy = @request.proxy if @request.proxy @client.connect_timeout = @request.open_timeout if @request.open_timeout @client.receive_timeout = @request.read_timeout if @request.read_timeout + @client.send_timeout = @request.write_timeout if @request.write_timeout end def setup_auth diff --git a/lib/httpi/adapter/net_http.rb b/lib/httpi/adapter/net_http.rb index 9aa3855..c31d0d5 100644 --- a/lib/httpi/adapter/net_http.rb +++ b/lib/httpi/adapter/net_http.rb @@ -155,6 +155,13 @@ def setup_client @client.use_ssl = @request.ssl? @client.open_timeout = @request.open_timeout if @request.open_timeout @client.read_timeout = @request.read_timeout if @request.read_timeout + if @request.write_timeout + if @client.respond_to?(:write_timeout=) # Since Ruby 2.6 + @client.write_timeout = @request.write_timeout + else + raise NotSupportedError, "Net::HTTP supports write_timeout since Ruby 2.6" + end + end end def setup_ssl_auth diff --git a/lib/httpi/adapter/net_http_persistent.rb b/lib/httpi/adapter/net_http_persistent.rb index 554cc4e..501c255 100644 --- a/lib/httpi/adapter/net_http_persistent.rb +++ b/lib/httpi/adapter/net_http_persistent.rb @@ -32,6 +32,7 @@ def setup_client @client.open_timeout = @request.open_timeout if @request.open_timeout @client.read_timeout = @request.read_timeout if @request.read_timeout + raise NotSupportedError, "Net::HTTP::Persistent does not support write_timeout" if @request.write_timeout end def thread_key diff --git a/lib/httpi/request.rb b/lib/httpi/request.rb index 8c0d071..8eebf9a 100644 --- a/lib/httpi/request.rb +++ b/lib/httpi/request.rb @@ -11,7 +11,7 @@ module HTTPI class Request # Available attribute writers. - ATTRIBUTES = [:url, :proxy, :headers, :body, :open_timeout, :read_timeout, :follow_redirect, :redirect_limit, :query] + ATTRIBUTES = [:url, :proxy, :headers, :body, :open_timeout, :read_timeout, :write_timeout, :follow_redirect, :redirect_limit, :query] # Accepts a Hash of +args+ to mass assign attributes and authentication credentials. def initialize(args = {}) @@ -90,7 +90,7 @@ def set_cookies(object_or_array) headers["Cookie"] = cookies if cookies end - attr_accessor :open_timeout, :read_timeout + attr_accessor :open_timeout, :read_timeout, :write_timeout attr_reader :body # Sets a body request given a String or a Hash. From eddfc13a1400cf9e49af442c63240559e63e8ddc Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 21:00:15 +0500 Subject: [PATCH 14/21] Move excon integration tests to the appropriate file --- spec/httpi/adapter/excon_spec.rb | 124 ------------------- spec/integration/excon_spec.rb | 36 ++++++ spec/integration/net_http_persistent_spec.rb | 2 +- 3 files changed, 37 insertions(+), 125 deletions(-) delete mode 100644 spec/httpi/adapter/excon_spec.rb diff --git a/spec/httpi/adapter/excon_spec.rb b/spec/httpi/adapter/excon_spec.rb deleted file mode 100644 index 52af8c2..0000000 --- a/spec/httpi/adapter/excon_spec.rb +++ /dev/null @@ -1,124 +0,0 @@ -require "spec_helper" -require "integration/support/server" - -describe HTTPI::Adapter::Excon do - - subject(:adapter) { :excon } - - context "http requests" do - before :all do - @server = IntegrationServer.run - end - - after :all do - @server.stop - end - - it "sends and receives HTTP headers" do - request = HTTPI::Request.new(@server.url + "x-header") - request.headers["X-Header"] = "HTTPI" - - response = HTTPI.get(request, adapter) - expect(response.body).to include("HTTPI") - end - - it "executes GET requests" do - response = HTTPI.get(@server.url, adapter) - expect(response.body).to eq("get") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes POST requests" do - response = HTTPI.post(@server.url, "xml", adapter) - expect(response.body).to eq("post") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes HEAD requests" do - response = HTTPI.head(@server.url, adapter) - expect(response.code).to eq(200) - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes PUT requests" do - response = HTTPI.put(@server.url, "xml", adapter) - expect(response.body).to eq("put") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes DELETE requests" do - response = HTTPI.delete(@server.url, adapter) - expect(response.body).to eq("delete") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "supports basic authentication" do - request = HTTPI::Request.new(@server.url + "basic-auth") - request.auth.basic("admin", "secret") - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("basic-auth") - end - - it "does not support ntlm authentication" do - request = HTTPI::Request.new(@server.url + "ntlm-auth") - request.auth.ntlm("tester", "vReqSoafRe5O") - - expect { HTTPI.get(request, adapter) }. - to raise_error(HTTPI::NotSupportedError, /does not support NTLM authentication/) - end - - it "supports disabling verify mode" do - request = HTTPI::Request.new(@server.url) - request.auth.ssl.verify_mode = :none - adapter_class = HTTPI::Adapter.load(adapter).new(request) - expect(adapter_class.client.data[:ssl_verify_peer]).to eq(false) - end - end - - # it does not support digest auth - - if RUBY_PLATFORM =~ /java/ - pending "Puma Server complains: SSL not supported on JRuby" - else - context "https requests" do - before :all do - @server = IntegrationServer.run(:ssl => true) - end - after :all do - @server.stop - end - - # it does not raise when no certificate was set up - it "works when no client cert is specified" do - request = HTTPI::Request.new(@server.url) - request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("get") - end - - it "works with client cert and key provided as file path" do - request = HTTPI::Request.new(@server.url) - request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file - request.auth.ssl.cert_file = "spec/fixtures/client_cert.pem" - request.auth.ssl.cert_key_file = "spec/fixtures/client_key.pem" - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("get") - end - - it "works with client cert and key set directly" do - request = HTTPI::Request.new(@server.url) - - request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file - request.auth.ssl.cert = OpenSSL::X509::Certificate.new File.open("spec/fixtures/client_cert.pem").read - request.auth.ssl.cert_key = OpenSSL::PKey.read File.open("spec/fixtures/client_key.pem").read - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("get") - end - end - end - -end diff --git a/spec/integration/excon_spec.rb b/spec/integration/excon_spec.rb index 31ad00b..5d3abc2 100644 --- a/spec/integration/excon_spec.rb +++ b/spec/integration/excon_spec.rb @@ -79,6 +79,21 @@ expect(response.body).to eq("basic-auth") end + it "does not support ntlm authentication" do + request = HTTPI::Request.new(@server.url + "ntlm-auth") + request.auth.ntlm("tester", "vReqSoafRe5O") + + expect { HTTPI.get(request, adapter) }. + to raise_error(HTTPI::NotSupportedError, /does not support NTLM authentication/) + end + + it "supports disabling verify mode" do + request = HTTPI::Request.new(@server.url) + request.auth.ssl.verify_mode = :none + adapter_class = HTTPI::Adapter.load(adapter).new(request) + expect(adapter_class.client.data[:ssl_verify_peer]).to eq(false) + end + it "supports chunked response" do request = HTTPI::Request.new(@server.url) res = "" @@ -113,6 +128,27 @@ response = HTTPI.get(request, adapter) expect(response.body).to eq("get") end + + it "works with client cert and key provided as file path" do + request = HTTPI::Request.new(@server.url) + request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file + request.auth.ssl.cert_file = "spec/fixtures/client_cert.pem" + request.auth.ssl.cert_key_file = "spec/fixtures/client_key.pem" + + response = HTTPI.get(request, adapter) + expect(response.body).to eq("get") + end + + it "works with client cert and key set directly" do + request = HTTPI::Request.new(@server.url) + + request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file + request.auth.ssl.cert = OpenSSL::X509::Certificate.new File.open("spec/fixtures/client_cert.pem").read + request.auth.ssl.cert_key = OpenSSL::PKey.read File.open("spec/fixtures/client_key.pem").read + + response = HTTPI.get(request, adapter) + expect(response.body).to eq("get") + end end end diff --git a/spec/integration/net_http_persistent_spec.rb b/spec/integration/net_http_persistent_spec.rb index cf4ff47..15f6a09 100644 --- a/spec/integration/net_http_persistent_spec.rb +++ b/spec/integration/net_http_persistent_spec.rb @@ -48,7 +48,7 @@ end it "executes POST requests" do - request = HTTPI::Request.new(url: @server.url, open_timeout: 1, read_timeout: 1, body: "xml") + request = HTTPI::Request.new(url: @server.url, body: "xml") response = HTTPI.post(request, adapter) expect(response.body).to eq("post") From 375b87bd301621f472829eb1e2e3bd74ff01d398 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 21:16:44 +0500 Subject: [PATCH 15/21] Move http integration tests to the appropriate file --- spec/httpi/adapter/http_spec.rb | 101 -------------------------------- spec/integration/http_spec.rb | 16 +++++ 2 files changed, 16 insertions(+), 101 deletions(-) delete mode 100644 spec/httpi/adapter/http_spec.rb diff --git a/spec/httpi/adapter/http_spec.rb b/spec/httpi/adapter/http_spec.rb deleted file mode 100644 index 34b482d..0000000 --- a/spec/httpi/adapter/http_spec.rb +++ /dev/null @@ -1,101 +0,0 @@ -require "spec_helper" -require "integration/support/server" - -describe HTTPI::Adapter::HTTP do - - subject(:adapter) { :http } - - context "http requests" do - before :all do - @server = IntegrationServer.run - end - - after :all do - @server.stop - end - - it "sends and receives HTTP headers" do - request = HTTPI::Request.new(@server.url + "x-header") - request.headers["X-Header"] = "HTTPI" - - response = HTTPI.get(request, adapter) - expect(response.body).to include("HTTPI") - end - - it "executes GET requests" do - response = HTTPI.get(@server.url, adapter) - expect(response.body).to eq("get") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes POST requests" do - response = HTTPI.post(@server.url, "xml", adapter) - expect(response.body).to eq("post") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes HEAD requests" do - response = HTTPI.head(@server.url, adapter) - expect(response.code).to eq(200) - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes PUT requests" do - response = HTTPI.put(@server.url, "xml", adapter) - expect(response.body).to eq("put") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes DELETE requests" do - response = HTTPI.delete(@server.url, adapter) - expect(response.body).to eq("delete") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "supports basic authentication" do - request = HTTPI::Request.new(@server.url + "basic-auth") - request.auth.basic("admin", "secret") - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("basic-auth") - end - - it "does not support digest authentication" do - request = HTTPI::Request.new(@server.url + "digest-auth") - request.auth.digest("admin", "secret") - - expect { HTTPI.get(request, adapter) }. - to raise_error(HTTPI::NotSupportedError, /does not support HTTP digest authentication/) - end - - it "does not support ntlm authentication" do - request = HTTPI::Request.new(@server.url + "ntlm-auth") - request.auth.ntlm("tester", "vReqSoafRe5O") - - expect { HTTPI.get(request, adapter) }. - to raise_error(HTTPI::NotSupportedError, /does not support NTLM digest authentication/) - end - end - - if RUBY_PLATFORM =~ /java/ - pending "Puma Server complains: SSL not supported on JRuby" - else - context "https requests" do - before :all do - @server = IntegrationServer.run(:ssl => true) - end - after :all do - @server.stop - end - - it "works when set up properly" do - request = HTTPI::Request.new(@server.url) - request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("get") - end - end - end - -end diff --git a/spec/integration/http_spec.rb b/spec/integration/http_spec.rb index e65cd1a..7d1157b 100644 --- a/spec/integration/http_spec.rb +++ b/spec/integration/http_spec.rb @@ -80,6 +80,22 @@ expect(response.body).to eq("basic-auth") end + it "does not support digest authentication" do + request = HTTPI::Request.new(@server.url + "digest-auth") + request.auth.digest("admin", "secret") + + expect { HTTPI.get(request, adapter) }. + to raise_error(HTTPI::NotSupportedError, /does not support HTTP digest authentication/) + end + + it "does not support ntlm authentication" do + request = HTTPI::Request.new(@server.url + "ntlm-auth") + request.auth.ntlm("tester", "vReqSoafRe5O") + + expect { HTTPI.get(request, adapter) }. + to raise_error(HTTPI::NotSupportedError, /does not support NTLM digest authentication/) + end + it "supports chunked response" do skip("Needs investigation") request = HTTPI::Request.new(@server.url) From a2310a2bdb2e081201d72f4dc843c9fcb45cd07b Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Thu, 23 Aug 2018 22:10:22 +0500 Subject: [PATCH 16/21] Move net_http_persistent integration tests to the appropriate file --- .../httpi/adapter/net_http_persistent_spec.rb | 96 ------------------- spec/integration/net_http_persistent_spec.rb | 8 ++ 2 files changed, 8 insertions(+), 96 deletions(-) delete mode 100644 spec/httpi/adapter/net_http_persistent_spec.rb diff --git a/spec/httpi/adapter/net_http_persistent_spec.rb b/spec/httpi/adapter/net_http_persistent_spec.rb deleted file mode 100644 index 8f02ec8..0000000 --- a/spec/httpi/adapter/net_http_persistent_spec.rb +++ /dev/null @@ -1,96 +0,0 @@ -require "spec_helper" -require "integration/support/server" - -describe HTTPI::Adapter::NetHTTPPersistent do - - subject(:adapter) { :net_http_persistent } - - context "http requests" do - before :all do - @server = IntegrationServer.run - end - - after :all do - @server.stop - end - - it "sends and receives HTTP headers" do - request = HTTPI::Request.new(@server.url + "x-header") - request.headers["X-Header"] = "HTTPI" - - response = HTTPI.get(request, adapter) - expect(response.body).to include("HTTPI") - end - - it "executes GET requests" do - response = HTTPI.get(@server.url, adapter) - expect(response.body).to eq("get") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes POST requests" do - response = HTTPI.post(@server.url, "xml", adapter) - expect(response.body).to eq("post") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes HEAD requests" do - response = HTTPI.head(@server.url, adapter) - expect(response.code).to eq(200) - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes PUT requests" do - response = HTTPI.put(@server.url, "xml", adapter) - expect(response.body).to eq("put") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes DELETE requests" do - response = HTTPI.delete(@server.url, adapter) - expect(response.body).to eq("delete") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "supports basic authentication" do - request = HTTPI::Request.new(@server.url + "basic-auth") - request.auth.basic("admin", "secret") - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("basic-auth") - end - - it "does not support ntlm authentication" do - request = HTTPI::Request.new(@server.url + "ntlm-auth") - request.auth.ntlm("tester", "vReqSoafRe5O") - - expect { HTTPI.get(request, adapter) }. - to raise_error(HTTPI::NotSupportedError, /does not support NTLM authentication/) - end - end - - # it does not support digest auth - - if RUBY_PLATFORM =~ /java/ - pending "Puma Server complains: SSL not supported on JRuby" - else - context "https requests" do - before :all do - @server = IntegrationServer.run(:ssl => true) - end - after :all do - @server.stop - end - - # it does not raise when no certificate was set up - it "works when set up properly" do - request = HTTPI::Request.new(@server.url) - request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("get") - end - end - end - -end diff --git a/spec/integration/net_http_persistent_spec.rb b/spec/integration/net_http_persistent_spec.rb index 15f6a09..c64b094 100644 --- a/spec/integration/net_http_persistent_spec.rb +++ b/spec/integration/net_http_persistent_spec.rb @@ -81,6 +81,14 @@ expect(response.body).to eq("basic-auth") end + it "does not support ntlm authentication" do + request = HTTPI::Request.new(@server.url + "ntlm-auth") + request.auth.ntlm("tester", "vReqSoafRe5O") + + expect { HTTPI.get(request, adapter) }. + to raise_error(HTTPI::NotSupportedError, /does not support NTLM authentication/) + end + # it does not support digest authentication it "supports chunked response" do From dd39a8d0efb513529c0971bae2ac572326728dfb Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Fri, 24 Aug 2018 10:09:04 +0500 Subject: [PATCH 17/21] Move net_http integration tests to the appropriate file --- spec/httpi/adapter/net_http_spec.rb | 198 ---------------------------- spec/integration/net_http_spec.rb | 107 ++++++++++++++- 2 files changed, 106 insertions(+), 199 deletions(-) delete mode 100644 spec/httpi/adapter/net_http_spec.rb diff --git a/spec/httpi/adapter/net_http_spec.rb b/spec/httpi/adapter/net_http_spec.rb deleted file mode 100644 index 51e94e2..0000000 --- a/spec/httpi/adapter/net_http_spec.rb +++ /dev/null @@ -1,198 +0,0 @@ -require "spec_helper" -require "integration/support/server" - -describe HTTPI::Adapter::NetHTTP do - - subject(:adapter) { :net_http } - - context "http requests" do - before :all do - @server = IntegrationServer.run - end - - after :all do - @server.stop - end - - context 'when socks is specified' do - - let(:socks_client) { mock('socks_client') } - let(:request){HTTPI::Request.new(@server.url)} - - it 'uses Net::HTTP.SOCKSProxy as client' do - socks_client.expects(:new).with(URI(@server.url).host, URI(@server.url).port).returns(:socks_client_instance) - Net::HTTP.expects(:SOCKSProxy).with('localhost', 8080).returns socks_client - - request.proxy = 'socks://localhost:8080' - adapter = HTTPI::Adapter::NetHTTP.new(request) - - expect(adapter.client).to eq(:socks_client_instance) - end - end - - it "sends and receives HTTP headers" do - request = HTTPI::Request.new(@server.url + "x-header") - request.headers["X-Header"] = "HTTPI" - - response = HTTPI.get(request, adapter) - expect(response.body).to include("HTTPI") - end - - it "executes GET requests" do - response = HTTPI.get(@server.url, adapter) - expect(response.body).to eq("get") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes POST requests" do - response = HTTPI.post(@server.url, "xml", adapter) - expect(response.body).to eq("post") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes HEAD requests" do - response = HTTPI.head(@server.url, adapter) - expect(response.code).to eq(200) - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes PUT requests" do - response = HTTPI.put(@server.url, "xml", adapter) - expect(response.body).to eq("put") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - it "executes DELETE requests" do - response = HTTPI.delete(@server.url, adapter) - expect(response.body).to eq("delete") - expect(response.headers["Content-Type"]).to eq("text/plain") - end - - context "supports custom methods supported by Net::HTTP" do - let(:request) do - HTTPI::Request.new(@server.url).tap do|r| - r.body = request_body if request_body - end - end - - let(:request_body) { nil } - - let(:response) { HTTPI.request(http_method, request, adapter) } - - shared_examples_for 'any supported custom method' do - specify { response.body.should eq http_method.to_s } - specify { response.headers["Content-Type"].should eq('text/plain') } - end - - context 'PATCH' do - let(:http_method) { :patch } - let(:request_body) { "xml" } - - it_behaves_like 'any supported custom method' - end - - context 'UNSUPPORTED method' do - let(:http_method) { :unsupported } - - specify { expect { response }.to raise_error HTTPI::NotSupportedError } - end - end - - it "supports basic authentication" do - request = HTTPI::Request.new(@server.url + "basic-auth") - request.auth.basic("admin", "secret") - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("basic-auth") - end - - it "does not support digest authentication" do - request = HTTPI::Request.new(@server.url + "digest-auth") - request.auth.digest("admin", "secret") - - expect { HTTPI.get(request, adapter) }. - to raise_error(HTTPI::NotSupportedError, /does not support HTTP digest authentication/) - end - - it "supports ntlm authentication" do - request = HTTPI::Request.new(@server.url + "ntlm-auth") - request.auth.ntlm("tester", "vReqSoafRe5O") - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("ntlm-auth") - end - - it 'does not support ntlm authentication when Net::NTLM is not available' do - Net.expects(:const_defined?).with(:NTLM).returns false - - request = HTTPI::Request.new(@server.url + 'ntlm-auth') - request.auth.ntlm("testing", "failures") - - expect { HTTPI.get(request, adapter) }. - to raise_error(HTTPI::NotSupportedError, /Net::NTLM is not available/) - end - - it 'does not require ntlm when ntlm authenication is not requested' do - HTTPI::Adapter::NetHTTP.any_instance.stubs(:check_net_ntlm_version!).raises(RuntimeError) - request = HTTPI::Request.new(@server.url) - expect(request.auth.ntlm?).to be false - - # make sure a request doesn't call ntlm check if we don't ask for it. - expect { HTTPI.get(request, adapter) }.not_to raise_error - HTTPI::Adapter::NetHTTP.any_instance.unstub(:check_net_ntlm_version!) - end - - it 'does check ntlm when ntlm authentication is requested' do - request = HTTPI::Request.new(@server.url + "ntlm-auth") - request.auth.ntlm("tester", "vReqSoafRe5O") - - expect { HTTPI.get(request, adapter) }.not_to raise_error - - # the check should also verify that the version of ntlm is supported and still fail if it isn't - HTTPI::Adapter::NetHTTP.any_instance.stubs(:ntlm_version).returns("0.1.1") - - request = HTTPI::Request.new(@server.url + "ntlm-auth") - request.auth.ntlm("tester", "vReqSoafRe5O") - - expect { HTTPI.get(request, adapter) }.to raise_error(ArgumentError, /Invalid version/) - - HTTPI::Adapter::NetHTTP.any_instance.unstub(:ntlm_version) - end - - it "does not crash when authenticate header is missing (on second request)" do - request = HTTPI::Request.new(@server.url + 'ntlm-auth') - request.auth.ntlm("tester", "vReqSoafRe5O") - - expect { HTTPI.get(request, adapter) }. - to_not raise_error - - expect { HTTPI.get(request, adapter) }. - to_not raise_error - end - end - - # it does not support digest auth - - if RUBY_PLATFORM =~ /java/ - pending "Puma Server complains: SSL not supported on JRuby" - else - context "https requests" do - before :all do - @server = IntegrationServer.run(:ssl => true) - end - after :all do - @server.stop - end - - # it does not raise when no certificate was set up - it "works when set up properly" do - request = HTTPI::Request.new(@server.url) - request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file - - response = HTTPI.get(request, adapter) - expect(response.body).to eq("get") - end - end - end - -end diff --git a/spec/integration/net_http_spec.rb b/spec/integration/net_http_spec.rb index ee722d4..b98844d 100644 --- a/spec/integration/net_http_spec.rb +++ b/spec/integration/net_http_spec.rb @@ -14,6 +14,21 @@ @server.stop end + context "when socks is specified" do + let(:socks_client) { mock("socks_client") } + let(:request) { HTTPI::Request.new(@server.url) } + + it "uses Net::HTTP.SOCKSProxy as client" do + socks_client.expects(:new).with(URI(@server.url).host, URI(@server.url).port).returns(:socks_client_instance) + Net::HTTP.expects(:SOCKSProxy).with("localhost", 8080).returns socks_client + + request.proxy = "socks://localhost:8080" + adapter = HTTPI::Adapter::NetHTTP.new(request) + + expect(adapter.client).to eq(:socks_client_instance) + end + end + it "sends and receives HTTP headers" do request = HTTPI::Request.new(@server.url + "x-header") request.headers["X-Header"] = "HTTPI" @@ -69,6 +84,34 @@ expect(response.headers["Content-Type"]).to eq("text/plain") end + context "custom methods" do + let(:request) { + HTTPI::Request.new(@server.url).tap do |r| + r.body = request_body if request_body + end + } + let(:request_body) { nil } + let(:response) { HTTPI.request(http_method, request, adapter) } + + shared_examples_for "any supported custom method" do + specify { response.body.should eq http_method.to_s } + specify { response.headers["Content-Type"].should eq("text/plain") } + end + + context "PATCH method" do + let(:http_method) { :patch } + let(:request_body) { "xml" } + + it_behaves_like "any supported custom method" + end + + context "UNSUPPORTED method" do + let(:http_method) { :unsupported } + + specify { expect { response }.to raise_error HTTPI::NotSupportedError } + end + end + it "supports basic authentication" do request = HTTPI::Request.new(@server.url + "basic-auth") request.auth.basic("admin", "secret") @@ -77,7 +120,69 @@ expect(response.body).to eq("basic-auth") end - # it does not support digest authentication + it "does not support digest authentication" do + request = HTTPI::Request.new(@server.url + "digest-auth") + request.auth.digest("admin", "secret") + + expect { HTTPI.get(request, adapter) }. + to raise_error(HTTPI::NotSupportedError, /does not support HTTP digest authentication/) + end + + it "supports ntlm authentication" do + request = HTTPI::Request.new(@server.url + "ntlm-auth") + request.auth.ntlm("tester", "vReqSoafRe5O") + + response = HTTPI.get(request, adapter) + expect(response.body).to eq("ntlm-auth") + end + + it "does not support ntlm authentication when Net::NTLM is not available" do + Net.expects(:const_defined?).with(:NTLM).returns false + + request = HTTPI::Request.new(@server.url + "ntlm-auth") + request.auth.ntlm("testing", "failures") + + expect { HTTPI.get(request, adapter) }. + to raise_error(HTTPI::NotSupportedError, /Net::NTLM is not available/) + end + + it "does not require ntlm when ntlm authenication is not requested" do + HTTPI::Adapter::NetHTTP.any_instance.stubs(:check_net_ntlm_version!).raises(RuntimeError) + request = HTTPI::Request.new(@server.url) + expect(request.auth.ntlm?).to be false + + # make sure a request doesn't call ntlm check if we don't ask for it. + expect { HTTPI.get(request, adapter) }.not_to raise_error + HTTPI::Adapter::NetHTTP.any_instance.unstub(:check_net_ntlm_version!) + end + + it "does check ntlm when ntlm authentication is requested" do + request = HTTPI::Request.new(@server.url + "ntlm-auth") + request.auth.ntlm("tester", "vReqSoafRe5O") + + expect { HTTPI.get(request, adapter) }.not_to raise_error + + # the check should also verify that the version of ntlm is supported and still fail if it isn't + HTTPI::Adapter::NetHTTP.any_instance.stubs(:ntlm_version).returns("0.1.1") + + request = HTTPI::Request.new(@server.url + "ntlm-auth") + request.auth.ntlm("tester", "vReqSoafRe5O") + + expect { HTTPI.get(request, adapter) }.to raise_error(ArgumentError, /Invalid version/) + + HTTPI::Adapter::NetHTTP.any_instance.unstub(:ntlm_version) + end + + it "does not crash when authenticate header is missing (on second request)" do + request = HTTPI::Request.new(@server.url + "ntlm-auth") + request.auth.ntlm("tester", "vReqSoafRe5O") + + expect { HTTPI.get(request, adapter) }. + to_not raise_error + + expect { HTTPI.get(request, adapter) }. + to_not raise_error + end it "supports chunked response" do request = HTTPI::Request.new(@server.url) From dc1c6969e3065333919335e4dbf7f7c697537f80 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Fri, 24 Aug 2018 11:15:06 +0500 Subject: [PATCH 18/21] Add tests for different timeout options to all adapters --- lib/httpi/adapter/net_http.rb | 4 +- spec/httpi/adapter/curb_spec.rb | 9 +++- spec/httpi/adapter/em_http_spec.rb | 13 ++++- spec/httpi/adapter/excon_spec.rb | 28 ++++++++++ spec/httpi/adapter/http_spec.rb | 28 ++++++++++ spec/httpi/adapter/httpclient_spec.rb | 14 +++++ .../httpi/adapter/net_http_persistent_spec.rb | 46 ++++++++++++++++ spec/httpi/adapter/net_http_spec.rb | 54 +++++++++++++++++++ spec/integration/net_http_spec.rb | 2 + 9 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 spec/httpi/adapter/excon_spec.rb create mode 100644 spec/httpi/adapter/http_spec.rb create mode 100644 spec/httpi/adapter/net_http_persistent_spec.rb create mode 100644 spec/httpi/adapter/net_http_spec.rb diff --git a/lib/httpi/adapter/net_http.rb b/lib/httpi/adapter/net_http.rb index c31d0d5..8376cd1 100644 --- a/lib/httpi/adapter/net_http.rb +++ b/lib/httpi/adapter/net_http.rb @@ -156,10 +156,10 @@ def setup_client @client.open_timeout = @request.open_timeout if @request.open_timeout @client.read_timeout = @request.read_timeout if @request.read_timeout if @request.write_timeout - if @client.respond_to?(:write_timeout=) # Since Ruby 2.6 + if @client.respond_to?(:write_timeout=) # Expected to appear in Ruby 2.6 @client.write_timeout = @request.write_timeout else - raise NotSupportedError, "Net::HTTP supports write_timeout since Ruby 2.6" + raise NotSupportedError, "Net::HTTP supports write_timeout starting from Ruby 2.6" end end end diff --git a/spec/httpi/adapter/curb_spec.rb b/spec/httpi/adapter/curb_spec.rb index 2c670e7..ec931b7 100644 --- a/spec/httpi/adapter/curb_spec.rb +++ b/spec/httpi/adapter/curb_spec.rb @@ -152,12 +152,19 @@ adapter.request(:get) end - it "is set if specified" do + it "is set if specified read_timeout" do request.read_timeout = 30 curb.expects(:timeout_ms=).with(30_000) adapter.request(:get) end + + it "is set if specified write_timeout" do + request.write_timeout = 30 + curb.expects(:timeout_ms=).with(30_000) + + adapter.request(:get) + end end describe "connect_timeout_ms" do diff --git a/spec/httpi/adapter/em_http_spec.rb b/spec/httpi/adapter/em_http_spec.rb index 4b82452..e0a6eda 100644 --- a/spec/httpi/adapter/em_http_spec.rb +++ b/spec/httpi/adapter/em_http_spec.rb @@ -118,7 +118,7 @@ end describe "receive_timeout" do - it "is passed as a connection option" do + it "is passed as a connection option (when read_timeout specified)" do request.read_timeout = 60 url = "http://example.com:80" @@ -128,6 +128,17 @@ adapter end + + it "is passed as a connection option (when write_timeout specified)" do + request.write_timeout = 60 + + url = "http://example.com:80" + connection_options = { inactivity_timeout: 60 } + + EventMachine::HttpRequest.expects(:new).with(url, connection_options) + + adapter + end end describe "set_auth" do diff --git a/spec/httpi/adapter/excon_spec.rb b/spec/httpi/adapter/excon_spec.rb new file mode 100644 index 0000000..e26ab32 --- /dev/null +++ b/spec/httpi/adapter/excon_spec.rb @@ -0,0 +1,28 @@ +require "spec_helper" +require "httpi/adapter/excon" +require "httpi/request" + +begin + HTTPI::Adapter.load_adapter(:excon) + + describe HTTPI::Adapter::Excon do + let(:adapter) { HTTPI::Adapter::Excon.new(request) } + let(:request) { HTTPI::Request.new("http://example.com") } + + describe "settings" do + describe "connect_timeout, read_timeout, write_timeout" do + it "are passed as connection options" do + request.open_timeout = 30 + request.read_timeout = 40 + request.write_timeout = 50 + + expect(adapter.client.data).to include( + connect_timeout: 30, + read_timeout: 40, + write_timeout: 50 + ) + end + end + end + end +end diff --git a/spec/httpi/adapter/http_spec.rb b/spec/httpi/adapter/http_spec.rb new file mode 100644 index 0000000..aa3e842 --- /dev/null +++ b/spec/httpi/adapter/http_spec.rb @@ -0,0 +1,28 @@ +require "spec_helper" +require "httpi/adapter/http" +require "httpi/request" + +begin + HTTPI::Adapter.load_adapter(:http) + + describe HTTPI::Adapter::HTTP do + let(:adapter) { HTTPI::Adapter::HTTP.new(request) } + let(:request) { HTTPI::Request.new("http://example.com") } + + describe "settings" do + describe "connect_timeout, read_timeout, write_timeout" do + it "are being set on the client" do + request.open_timeout = 30 + request.read_timeout = 40 + request.write_timeout = 50 + + expect(adapter.client.default_options.timeout_options).to eq( + connect_timeout: 30, + read_timeout: 40, + write_timeout: 50 + ) + end + end + end + end +end diff --git a/spec/httpi/adapter/httpclient_spec.rb b/spec/httpi/adapter/httpclient_spec.rb index 41ca299..e6371a3 100644 --- a/spec/httpi/adapter/httpclient_spec.rb +++ b/spec/httpi/adapter/httpclient_spec.rb @@ -100,6 +100,20 @@ end end + describe "send_timeout" do + it "is not set unless specified" do + httpclient.expects(:send_timeout=).never + adapter.request(:get) + end + + it "is set if specified" do + request.write_timeout = 30 + + httpclient.expects(:send_timeout=).with(30) + adapter.request(:get) + end + end + describe "set_auth" do it "is set for HTTP basic auth" do request.auth.basic "username", "password" diff --git a/spec/httpi/adapter/net_http_persistent_spec.rb b/spec/httpi/adapter/net_http_persistent_spec.rb new file mode 100644 index 0000000..9ed7a5f --- /dev/null +++ b/spec/httpi/adapter/net_http_persistent_spec.rb @@ -0,0 +1,46 @@ +require "spec_helper" +require "httpi/adapter/net_http_persistent" +require "httpi/request" + +begin + HTTPI::Adapter.load_adapter(:net_http_persistent) + + describe HTTPI::Adapter::NetHTTPPersistent do + let(:adapter) { HTTPI::Adapter::NetHTTPPersistent.new(request) } + let(:request) { HTTPI::Request.new("http://example.com") } + + let(:response) { + Object.new.tap do |r| + r.stubs(:code).returns(200) + r.stubs(:body).returns("abc") + r.stubs(:to_hash).returns({"Content-Length" => "3"}) + end + } + + before do + Net::HTTP::Persistent.any_instance.stubs(:start).returns(response) + end + + describe "settings" do + describe "open_timeout, read_timeout" do + it "are being set on the client" do + request.open_timeout = 30 + request.read_timeout = 40 + + adapter.client.expects(:open_timeout=).with(30) + adapter.client.expects(:read_timeout=).with(40) + + adapter.request(:get) + end + end + + describe "write_timeout" do + it "is not supported" do + request.write_timeout = 50 + expect { adapter.request(:get) } + .to raise_error(HTTPI::NotSupportedError, /write_timeout/) + end + end + end + end +end diff --git a/spec/httpi/adapter/net_http_spec.rb b/spec/httpi/adapter/net_http_spec.rb new file mode 100644 index 0000000..346b569 --- /dev/null +++ b/spec/httpi/adapter/net_http_spec.rb @@ -0,0 +1,54 @@ +require "spec_helper" +require "httpi/adapter/net_http" +require "httpi/request" + +begin + HTTPI::Adapter.load_adapter(:net_http) + + describe HTTPI::Adapter::NetHTTP do + let(:adapter) { HTTPI::Adapter::NetHTTP.new(request) } + let(:request) { HTTPI::Request.new("http://example.com") } + + let(:response) { + Object.new.tap do |r| + r.stubs(:code).returns(200) + r.stubs(:body).returns("abc") + r.stubs(:to_hash).returns({"Content-Length" => "3"}) + end + } + + before do + Net::HTTP.any_instance.stubs(:start).returns(response) + end + + describe "settings" do + describe "open_timeout, read_timeout" do + it "are being set on the client" do + request.open_timeout = 30 + request.read_timeout = 40 + + adapter.client.expects(:open_timeout=).with(30) + adapter.client.expects(:read_timeout=).with(40) + + adapter.request(:get) + end + end + + describe "write_timeout" do + if Net::HTTP.method_defined?(:write_timeout=) + it "is being set on the client" do + request.write_timeout = 50 + adapter.client.expects(:write_timeout=).with(50) + adapter.request(:get) + end + else + it "can not be set on the client" do + request.write_timeout = 50 + expect { adapter.request(:get) } + .to raise_error(HTTPI::NotSupportedError, /write_timeout/) + end + end + end + end + end +end diff --git a/spec/integration/net_http_spec.rb b/spec/integration/net_http_spec.rb index b98844d..9b34fe8 100644 --- a/spec/integration/net_http_spec.rb +++ b/spec/integration/net_http_spec.rb @@ -46,6 +46,8 @@ end it "it supports read timeout" do + require "net/http" + request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds From 7bffabfca789bb1c7c709b84974b21fd7c14c6f9 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Fri, 24 Aug 2018 11:56:44 +0500 Subject: [PATCH 19/21] Extend all timeout exceptions with ::HTTPI::TimeoutError (it is module now!) --- lib/httpi.rb | 2 +- lib/httpi/adapter/curb.rb | 3 +++ lib/httpi/adapter/em_http.rb | 7 ++++++- lib/httpi/adapter/excon.rb | 3 +++ lib/httpi/adapter/http.rb | 12 ++++++------ lib/httpi/adapter/httpclient.rb | 3 +++ lib/httpi/adapter/net_http.rb | 3 +++ lib/httpi/adapter/net_http_persistent.rb | 11 +++++++++++ spec/integration/curb_spec.rb | 8 +++++--- spec/integration/em_http_spec.rb | 8 +++++--- spec/integration/excon_spec.rb | 8 +++++--- spec/integration/http_spec.rb | 8 +++++--- spec/integration/httpclient_spec.rb | 8 +++++--- spec/integration/net_http_persistent_spec.rb | 9 ++++++--- spec/integration/net_http_spec.rb | 8 +++++--- 15 files changed, 72 insertions(+), 29 deletions(-) diff --git a/lib/httpi.rb b/lib/httpi.rb index 514ef14..6e11f24 100644 --- a/lib/httpi.rb +++ b/lib/httpi.rb @@ -86,11 +86,11 @@ module HTTPI DEFAULT_LOG_LEVEL = :debug class Error < StandardError; end - class TimeoutError < Error; end class NotSupportedError < Error; end class NotImplementedError < Error; end module ConnectionError; end + module TimeoutError; end class SSLError < Error def initialize(message = nil, original = $!) diff --git a/lib/httpi/adapter/curb.rb b/lib/httpi/adapter/curb.rb index 99fc3b0..2eb5b7f 100644 --- a/lib/httpi/adapter/curb.rb +++ b/lib/httpi/adapter/curb.rb @@ -46,6 +46,9 @@ def request(method) rescue Curl::Err::ConnectionFailedError # connection refused $!.extend ConnectionError raise + rescue Curl::Err::TimeoutError + $!.extend TimeoutError + raise end private diff --git a/lib/httpi/adapter/em_http.rb b/lib/httpi/adapter/em_http.rb index 412bbf3..e2fc0c6 100644 --- a/lib/httpi/adapter/em_http.rb +++ b/lib/httpi/adapter/em_http.rb @@ -29,6 +29,8 @@ module Adapter # are supported by em-httprequest but not HTTPI. class EmHttpRequest < Base + class EmHttpTimeoutError < StandardError; end # Generic error for timeouts + register :em_http, :deps => %w(em-synchrony em-synchrony/em-http em-http) def initialize(request) @@ -48,6 +50,9 @@ def cert_directory # @see HTTPI.request def request(method) _request { |options| @client.send method, options } + rescue EmHttpTimeoutError + $!.extend TimeoutError + raise end private @@ -106,7 +111,7 @@ def setup_http_auth(options) end def respond_with(http, start_time) - raise TimeoutError, "EM-HTTP-Request connection timed out: #{Time.now - start_time} sec" if http.response_header.status.zero? + raise EmHttpTimeoutError, "EM-HTTP-Request connection timed out: #{Time.now - start_time} sec" if http.response_header.status.zero? Response.new http.response_header.status, convert_headers(http.response_header), http.response diff --git a/lib/httpi/adapter/excon.rb b/lib/httpi/adapter/excon.rb index a03cd8f..19f0eb6 100644 --- a/lib/httpi/adapter/excon.rb +++ b/lib/httpi/adapter/excon.rb @@ -31,6 +31,9 @@ def request(method) $!.extend ConnectionError end raise + rescue ::Excon::Error::Timeout + $!.extend TimeoutError + raise end private diff --git a/lib/httpi/adapter/http.rb b/lib/httpi/adapter/http.rb index 8b702c0..15ea8c9 100644 --- a/lib/httpi/adapter/http.rb +++ b/lib/httpi/adapter/http.rb @@ -32,13 +32,13 @@ def request(method) unless ::HTTP::Request::METHODS.include? method raise NotSupportedError, "http.rb does not support custom HTTP methods" end - response = begin - @client.send(method, @request.url, :body => @request.body) - rescue OpenSSL::SSL::SSLError - raise SSLError - end - + response = @client.send(method, @request.url, :body => @request.body) Response.new(response.code, response.headers.to_h, response.body.to_s) + rescue OpenSSL::SSL::SSLError + raise SSLError + rescue ::HTTP::TimeoutError + $!.extend TimeoutError + raise end private diff --git a/lib/httpi/adapter/httpclient.rb b/lib/httpi/adapter/httpclient.rb index 9165805..7175aa9 100644 --- a/lib/httpi/adapter/httpclient.rb +++ b/lib/httpi/adapter/httpclient.rb @@ -29,6 +29,9 @@ def request(method) rescue Errno::ECONNREFUSED # connection refused $!.extend ConnectionError raise + rescue ::HTTPClient::TimeoutError + $!.extend TimeoutError + raise end private diff --git a/lib/httpi/adapter/net_http.rb b/lib/httpi/adapter/net_http.rb index 8376cd1..3f57e3b 100644 --- a/lib/httpi/adapter/net_http.rb +++ b/lib/httpi/adapter/net_http.rb @@ -52,6 +52,9 @@ def request(method) rescue Errno::ECONNREFUSED # connection refused $!.extend ConnectionError raise + rescue ::Timeout::Error + $!.extend TimeoutError + raise end private diff --git a/lib/httpi/adapter/net_http_persistent.rb b/lib/httpi/adapter/net_http_persistent.rb index 501c255..ba440c9 100644 --- a/lib/httpi/adapter/net_http_persistent.rb +++ b/lib/httpi/adapter/net_http_persistent.rb @@ -9,6 +9,17 @@ class NetHTTPPersistent < NetHTTP register :net_http_persistent, :deps => %w(net/http/persistent) + # Executes arbitrary HTTP requests. + # @see HTTPI.request + def request(method) + super + rescue Net::HTTP::Persistent::Error => e + if !e.message.nil? && e.message =~ /Timeout/ + $!.extend TimeoutError + end + raise + end + private def create_client diff --git a/spec/integration/curb_spec.rb b/spec/integration/curb_spec.rb index 598a82a..d336849 100644 --- a/spec/integration/curb_spec.rb +++ b/spec/integration/curb_spec.rb @@ -39,9 +39,11 @@ request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds - expect do - HTTPI.get(request, adapter) - end.to raise_exception(Curl::Err::TimeoutError) + expect { HTTPI.get(request, adapter) } + .to raise_error { |error| + expect(error).to be_a(Curl::Err::TimeoutError) + expect(error).to be_a(HTTPI::TimeoutError) + } end it "executes GET requests" do diff --git a/spec/integration/em_http_spec.rb b/spec/integration/em_http_spec.rb index fb04bdf..96c6504 100644 --- a/spec/integration/em_http_spec.rb +++ b/spec/integration/em_http_spec.rb @@ -46,9 +46,11 @@ request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds - expect do - HTTPI.get(request, adapter) - end.to raise_exception(HTTPI::TimeoutError) + expect { HTTPI.get(request, adapter) } + .to raise_error { |error| + expect(error).to be_a(HTTPI::Adapter::EmHttpRequest::EmHttpTimeoutError) + expect(error).to be_a(HTTPI::TimeoutError) + } end it "executes GET requests" do diff --git a/spec/integration/excon_spec.rb b/spec/integration/excon_spec.rb index 5d3abc2..29ddc27 100644 --- a/spec/integration/excon_spec.rb +++ b/spec/integration/excon_spec.rb @@ -36,9 +36,11 @@ request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds - expect do - HTTPI.get(request, adapter) - end.to raise_exception(Excon::Error::Timeout) + expect { HTTPI.get(request, adapter) } + .to raise_error { |error| + expect(error).to be_a(Excon::Error::Timeout) + expect(error).to be_a(HTTPI::TimeoutError) + } end it "executes GET requests" do diff --git a/spec/integration/http_spec.rb b/spec/integration/http_spec.rb index 7d1157b..1fc1d00 100644 --- a/spec/integration/http_spec.rb +++ b/spec/integration/http_spec.rb @@ -36,9 +36,11 @@ request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds - expect do - HTTPI.get(request, adapter) - end.to raise_exception(HTTP::TimeoutError) + expect { HTTPI.get(request, adapter) } + .to raise_error { |error| + expect(error).to be_a(HTTP::TimeoutError) + expect(error).to be_a(HTTPI::TimeoutError) + } end diff --git a/spec/integration/httpclient_spec.rb b/spec/integration/httpclient_spec.rb index be52cb8..a980f20 100644 --- a/spec/integration/httpclient_spec.rb +++ b/spec/integration/httpclient_spec.rb @@ -36,9 +36,11 @@ request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds - expect do - HTTPI.get(request, adapter) - end.to raise_exception(HTTPClient::ReceiveTimeoutError) + expect { HTTPI.get(request, adapter) } + .to raise_error { |error| + expect(error).to be_a(HTTPClient::ReceiveTimeoutError) + expect(error).to be_a(HTTPI::TimeoutError) + } end it "executes GET requests" do diff --git a/spec/integration/net_http_persistent_spec.rb b/spec/integration/net_http_persistent_spec.rb index c64b094..9dd2bbc 100644 --- a/spec/integration/net_http_persistent_spec.rb +++ b/spec/integration/net_http_persistent_spec.rb @@ -36,9 +36,12 @@ request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds - expect do - HTTPI.get(request, adapter) - end.to raise_exception(Net::HTTP::Persistent::Error, /Net::ReadTimeout/) + expect { HTTPI.get(request, adapter) } + .to raise_error { |error| + expect(error.message).to match(/Net::ReadTimeout/) + expect(error).to be_a(Net::HTTP::Persistent::Error) + expect(error).to be_a(HTTPI::TimeoutError) + } end it "executes GET requests" do diff --git a/spec/integration/net_http_spec.rb b/spec/integration/net_http_spec.rb index 9b34fe8..ae7ec9b 100644 --- a/spec/integration/net_http_spec.rb +++ b/spec/integration/net_http_spec.rb @@ -51,9 +51,11 @@ request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds - expect do - HTTPI.get(request, adapter) - end.to raise_exception(Net::ReadTimeout) + expect { HTTPI.get(request, adapter) } + .to raise_error { |error| + expect(error).to be_a(Net::ReadTimeout) + expect(error).to be_a(HTTPI::TimeoutError) + } end it "executes GET requests" do From 3453c7cf6bc72af56506c493b491a80cabe9e500 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Fri, 24 Aug 2018 12:32:35 +0500 Subject: [PATCH 20/21] No need to require http libs, because errors classes are checked lazily now --- spec/integration/curb_spec.rb | 2 -- spec/integration/excon_spec.rb | 2 -- spec/integration/http_spec.rb | 2 -- spec/integration/httpclient_spec.rb | 2 -- spec/integration/net_http_persistent_spec.rb | 2 -- spec/integration/net_http_spec.rb | 2 -- 6 files changed, 12 deletions(-) diff --git a/spec/integration/curb_spec.rb b/spec/integration/curb_spec.rb index d336849..d8f45a7 100644 --- a/spec/integration/curb_spec.rb +++ b/spec/integration/curb_spec.rb @@ -34,8 +34,6 @@ end it "it supports read timeout" do - require "curb" - request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds diff --git a/spec/integration/excon_spec.rb b/spec/integration/excon_spec.rb index 29ddc27..8d5de2f 100644 --- a/spec/integration/excon_spec.rb +++ b/spec/integration/excon_spec.rb @@ -31,8 +31,6 @@ end it "it supports read timeout" do - require "excon" - request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds diff --git a/spec/integration/http_spec.rb b/spec/integration/http_spec.rb index 1fc1d00..de379c2 100644 --- a/spec/integration/http_spec.rb +++ b/spec/integration/http_spec.rb @@ -31,8 +31,6 @@ end it "it supports read timeout" do - require "http" - request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds diff --git a/spec/integration/httpclient_spec.rb b/spec/integration/httpclient_spec.rb index a980f20..6e02f5e 100644 --- a/spec/integration/httpclient_spec.rb +++ b/spec/integration/httpclient_spec.rb @@ -31,8 +31,6 @@ end it "it supports read timeout" do - require "httpclient" - request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds diff --git a/spec/integration/net_http_persistent_spec.rb b/spec/integration/net_http_persistent_spec.rb index 9dd2bbc..81b27f3 100644 --- a/spec/integration/net_http_persistent_spec.rb +++ b/spec/integration/net_http_persistent_spec.rb @@ -31,8 +31,6 @@ end it "it supports read timeout" do - require "net/http/persistent" - request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds diff --git a/spec/integration/net_http_spec.rb b/spec/integration/net_http_spec.rb index ae7ec9b..04b073c 100644 --- a/spec/integration/net_http_spec.rb +++ b/spec/integration/net_http_spec.rb @@ -46,8 +46,6 @@ end it "it supports read timeout" do - require "net/http" - request = HTTPI::Request.new(@server.url + "timeout") request.read_timeout = 0.5 # seconds From 5dcf101687a0a609fece321b949cf4a5c4c69177 Mon Sep 17 00:00:00 2001 From: Alexey Chernenkov Date: Fri, 24 Aug 2018 13:05:23 +0500 Subject: [PATCH 21/21] Disable read_timeout test for em_http_request adapter on jruby --- spec/integration/em_http_spec.rb | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/spec/integration/em_http_spec.rb b/spec/integration/em_http_spec.rb index 96c6504..21be266 100644 --- a/spec/integration/em_http_spec.rb +++ b/spec/integration/em_http_spec.rb @@ -42,15 +42,23 @@ expect(response.headers["Set-Cookie"]).to eq(cookies) end - it "it supports read timeout" do - request = HTTPI::Request.new(@server.url + "timeout") - request.read_timeout = 0.5 # seconds - - expect { HTTPI.get(request, adapter) } - .to raise_error { |error| - expect(error).to be_a(HTTPI::Adapter::EmHttpRequest::EmHttpTimeoutError) - expect(error).to be_a(HTTPI::TimeoutError) - } + if RUBY_PLATFORM =~ /java/ + pending <<-MSG + It seems like JRuby is missing support for inactivity timeout! See related issues on GitHub: + - https://github.com/eventmachine/eventmachine/issues/155 + - https://github.com/eventmachine/eventmachine/pull/312 + MSG + else + it "it supports read timeout" do + request = HTTPI::Request.new(@server.url + "timeout") + request.read_timeout = 0.5 # seconds + + expect { HTTPI.get(request, adapter) } + .to raise_error { |error| + expect(error).to be_a(HTTPI::Adapter::EmHttpRequest::EmHttpTimeoutError) + expect(error).to be_a(HTTPI::TimeoutError) + } + end end it "executes GET requests" do