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 f6afb41..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
@@ -72,8 +75,9 @@ 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
+ 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
# cURL workaround
diff --git a/lib/httpi/adapter/em_http.rb b/lib/httpi/adapter/em_http.rb
index 3aeb58d..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
@@ -69,10 +74,11 @@ def _request
end
def connection_options
- options = {
- :connect_timeout => @request.open_timeout,
- :inactivity_timeout => @request.read_timeout
- }
+ options = {}
+
+ 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
@@ -105,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 b80396b..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
@@ -58,6 +61,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 e60e787..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
@@ -73,6 +73,12 @@ 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
+ timeouts[:write] = @request.write_timeout if @request.write_timeout
+ client = client.timeout(timeouts) if timeouts.any?
+
client.headers(@request.headers)
end
end
diff --git a/lib/httpi/adapter/httpclient.rb b/lib/httpi/adapter/httpclient.rb
index 97cd56b..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
@@ -45,6 +48,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..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
@@ -155,6 +158,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=) # Expected to appear in Ruby 2.6
+ @client.write_timeout = @request.write_timeout
+ else
+ raise NotSupportedError, "Net::HTTP supports write_timeout starting from 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..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
@@ -32,6 +43,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.
diff --git a/spec/httpi/adapter/curb_spec.rb b/spec/httpi/adapter/curb_spec.rb
index b624447..ec931b7 100644
--- a/spec/httpi/adapter/curb_spec.rb
+++ b/spec/httpi/adapter/curb_spec.rb
@@ -146,29 +146,36 @@
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
+ it "is set if specified read_timeout" do
request.read_timeout = 30
- curb.expects(:timeout=).with(request.read_timeout)
+ 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" 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
diff --git a/spec/httpi/adapter/em_http_spec.rb b/spec/httpi/adapter/em_http_spec.rb
index a171138..e0a6eda 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)
@@ -121,11 +118,22 @@
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'
- 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)
+
+ 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)
diff --git a/spec/httpi/adapter/excon_spec.rb b/spec/httpi/adapter/excon_spec.rb
index 52af8c2..e26ab32 100644
--- a/spec/httpi/adapter/excon_spec.rb
+++ b/spec/httpi/adapter/excon_spec.rb
@@ -1,124 +1,28 @@
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")
+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
index 34b482d..aa3e842 100644
--- a/spec/httpi/adapter/http_spec.rb
+++ b/spec/httpi/adapter/http_spec.rb
@@ -1,101 +1,28 @@
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")
+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
index 8f02ec8..9ed7a5f 100644
--- a/spec/httpi/adapter/net_http_persistent_spec.rb
+++ b/spec/httpi/adapter/net_http_persistent_spec.rb
@@ -1,96 +1,46 @@
require "spec_helper"
-require "integration/support/server"
+require "httpi/adapter/net_http_persistent"
+require "httpi/request"
-describe HTTPI::Adapter::NetHTTPPersistent do
+begin
+ HTTPI::Adapter.load_adapter(:net_http_persistent)
- subject(:adapter) { :net_http_persistent }
+ describe HTTPI::Adapter::NetHTTPPersistent do
+ let(:adapter) { HTTPI::Adapter::NetHTTPPersistent.new(request) }
+ let(:request) { HTTPI::Request.new("http://example.com") }
- 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")
+ 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
+ }
- response = HTTPI.get(request, adapter)
- expect(response.body).to eq("basic-auth")
+ before do
+ Net::HTTP::Persistent.any_instance.stubs(:start).returns(response)
end
- it "does not support ntlm authentication" do
- request = HTTPI::Request.new(@server.url + "ntlm-auth")
- request.auth.ntlm("tester", "vReqSoafRe5O")
+ 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
- expect { HTTPI.get(request, adapter) }.
- to raise_error(HTTPI::NotSupportedError, /does not support NTLM authentication/)
- end
- end
-
- # it does not support digest auth
+ adapter.client.expects(:open_timeout=).with(30)
+ adapter.client.expects(:read_timeout=).with(40)
- 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)
+ adapter.request(:get)
+ end
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")
+ 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
index 51e94e2..346b569 100644
--- a/spec/httpi/adapter/net_http_spec.rb
+++ b/spec/httpi/adapter/net_http_spec.rb
@@ -1,198 +1,54 @@
require "spec_helper"
-require "integration/support/server"
+require "httpi/adapter/net_http"
+require "httpi/request"
-describe HTTPI::Adapter::NetHTTP do
+begin
+ HTTPI::Adapter.load_adapter(:net_http)
- subject(:adapter) { :net_http }
+ describe HTTPI::Adapter::NetHTTP do
+ let(:adapter) { HTTPI::Adapter::NetHTTP.new(request) }
+ let(:request) { HTTPI::Request.new("http://example.com") }
- 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)
+ 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
- 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")
+ before do
+ Net::HTTP.any_instance.stubs(:start).returns(response)
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
+ 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
- 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
+ adapter.client.expects(:open_timeout=).with(30)
+ adapter.client.expects(:read_timeout=).with(40)
- 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
+ adapter.request(:get)
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")
+ 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/curb_spec.rb b/spec/integration/curb_spec.rb
index a13af0f..d8f45a7 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
+ 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(Curl::Err::TimeoutError)
+ expect(error).to be_a(HTTPI::TimeoutError)
+ }
+ end
+
it "executes GET requests" do
response = HTTPI.get(@server.url, adapter)
expect(response.body).to eq("get")
diff --git a/spec/integration/em_http_spec.rb b/spec/integration/em_http_spec.rb
index e980b1e..21be266 100644
--- a/spec/integration/em_http_spec.rb
+++ b/spec/integration/em_http_spec.rb
@@ -42,6 +42,25 @@
expect(response.headers["Set-Cookie"]).to eq(cookies)
end
+ 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
response = HTTPI.get(@server.url, adapter)
expect(response.body).to eq("get")
diff --git a/spec/integration/excon_spec.rb b/spec/integration/excon_spec.rb
index ed45b58..8d5de2f 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
+ 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(Excon::Error::Timeout)
+ expect(error).to be_a(HTTPI::TimeoutError)
+ }
+ end
+
it "executes GET requests" do
response = HTTPI.get(@server.url, adapter)
expect(response.body).to eq("get")
@@ -68,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 = ""
@@ -102,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/http_spec.rb b/spec/integration/http_spec.rb
index 5f167d3..de379c2 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
+ 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(HTTP::TimeoutError)
+ expect(error).to be_a(HTTPI::TimeoutError)
+ }
+ end
+
+
it "executes GET requests" do
response = HTTPI.get(@server.url, adapter)
expect(response.body).to eq("get")
@@ -68,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)
diff --git a/spec/integration/httpclient_spec.rb b/spec/integration/httpclient_spec.rb
index 934a060..6e02f5e 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
+ 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(HTTPClient::ReceiveTimeoutError)
+ expect(error).to be_a(HTTPI::TimeoutError)
+ }
+ end
+
it "executes GET requests" do
response = HTTPI.get(@server.url, adapter)
expect(response.body).to eq("get")
diff --git a/spec/integration/net_http_persistent_spec.rb b/spec/integration/net_http_persistent_spec.rb
index 28aabbf..81b27f3 100644
--- a/spec/integration/net_http_persistent_spec.rb
+++ b/spec/integration/net_http_persistent_spec.rb
@@ -30,6 +30,18 @@
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.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
response = HTTPI.get(@server.url, adapter)
expect(response.body).to eq("get")
@@ -37,8 +49,8 @@
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")
expect(response.headers["Content-Type"]).to eq("text/plain")
@@ -70,6 +82,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
diff --git a/spec/integration/net_http_spec.rb b/spec/integration/net_http_spec.rb
index fcee178..04b073c 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"
@@ -30,6 +45,17 @@
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(Net::ReadTimeout)
+ expect(error).to be_a(HTTPI::TimeoutError)
+ }
+ end
+
it "executes GET requests" do
response = HTTPI.get(@server.url, adapter)
expect(response.body).to eq("get")
@@ -60,6 +86,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")
@@ -68,7 +122,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)
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