Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #158 from dim/master

Added support for Excon
  • Loading branch information...
commit e6a9e81b8d2ce4a3fcfa83f1119ba878775c5774 2 parents 52d7f0b + cda6468
@bblimke authored
View
1  lib/webmock.rb
@@ -14,6 +14,7 @@
require 'webmock/http_lib_adapters/curb_adapter'
require 'webmock/http_lib_adapters/em_http_request_adapter'
require 'webmock/http_lib_adapters/typhoeus_hydra_adapter'
+require 'webmock/http_lib_adapters/excon_adapter'
require 'webmock/errors'
View
94 lib/webmock/http_lib_adapters/excon_adapter.rb
@@ -0,0 +1,94 @@
+begin
+ require 'excon'
+rescue LoadError
+ # excon not found
+end
+
+if defined?(Excon)
+
+ module WebMock
+ module HttpLibAdapters
+
+ class ExconAdapter < HttpLibAdapter
+ adapter_for :excon
+
+ def self.enable!
+ Excon.send(:remove_const, :Connection)
+ Excon.send(:const_set, :Connection, ExconConnection)
+ end
+
+ def self.disable!
+ Excon.send(:remove_const, :Connection)
+ Excon.send(:const_set, :Connection, ExconConnection.superclass)
+ end
+
+
+ def self.to_query(hash)
+ string = ""
+ for key, values in hash
+ if values.nil?
+ string << key.to_s << '&'
+ else
+ for value in [*values]
+ string << key.to_s << '=' << CGI.escape(value.to_s) << '&'
+ end
+ end
+ end
+ string.chop! # remove trailing '&'
+ end
+
+ def self.build_request(params)
+ params = params.dup
+ method = (params.delete(:method) || :get).to_s.downcase.to_sym
+ params[:query] = to_query(params[:query]) if params[:query].is_a?(Hash)
+ uri = Addressable::URI.new(params).to_s
+ WebMock::RequestSignature.new method, uri, :body => params[:body], :headers => params[:headers]
+ end
+
+ def self.real_response(mock)
+ raise Excon::Errors::Timeout if mock.should_timeout
+ mock.raise_error_if_any
+ Excon::Response.new \
+ :body => mock.body,
+ :status => mock.status[0].to_i,
+ :headers => mock.headers
+ end
+
+ def self.mock_response(real)
+ mock = WebMock::Response.new
+ mock.status = real.status
+ mock.headers = real.headers
+ mock.body = real.body
+ mock
+ end
+
+ def self.perform_callbacks(request, response, options = {})
+ return unless WebMock::CallbackRegistry.any_callbacks?
+ WebMock::CallbackRegistry.invoke_callbacks(options.merge(:lib => :excon), request, response)
+ end
+
+ end
+
+ class ExconConnection < ::Excon::Connection
+
+ def request_kernel(params, &block)
+ mock_request = ExconAdapter.build_request params.dup
+ WebMock::RequestRegistry.instance.requested_signatures.put(mock_request)
+
+ if mock_response = WebMock::StubRegistry.instance.response_for_request(mock_request)
+ ExconAdapter.perform_callbacks(mock_request, mock_response, :real_request => false)
+ ExconAdapter.real_response(mock_response)
+ elsif WebMock.net_connect_allowed?(mock_request.uri)
+ real_response = super
+ ExconAdapter.perform_callbacks(mock_request, ExconAdapter.mock_response(real_response), :real_request => true)
+ real_response
+ else
+ raise WebMock::NetConnectNotAllowedError.new(mock_request)
+ end
+ end
+
+ end
+ end
+ end
+
+end
View
15 spec/acceptance/excon/excon_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+require 'acceptance/webmock_shared'
+require 'acceptance/excon/excon_spec_helper'
+
+describe "Excon" do
+ include ExconSpecHelper
+ include_context "with WebMock"
+
+ it 'should allow Excon requests to use query hash paramters' do
+ stub_request(:get, "http://example.com/resource/?a=1&b=2").to_return(:body => "abc")
+ Excon.get('http://example.com', :path => "resource/", :query => {:a => 1, :b => 2}).body.should == "abc"
+ end
+
+end
+
View
37 spec/acceptance/excon/excon_spec_helper.rb
@@ -0,0 +1,37 @@
+require 'ostruct'
+
+module ExconSpecHelper
+
+ def http_request(method, uri, options = {}, &block)
+ uri = Addressable::URI.heuristic_parse(uri)
+ uri = uri.omit(:userinfo).to_s.gsub(' ', '+')
+
+ options = options.merge(:method => method) # Dup and merge
+ response = Excon.new(uri).request(options, &block)
+
+ headers = WebMock::Util::Headers.normalize_headers(response.headers)
+ headers = headers.inject({}) do |res, (name, value)|
+ res[name] = value.is_a?(Array) ? value.flatten.join(', ') : value
+ res
+ end
+
+ OpenStruct.new \
+ :body => response.body,
+ :headers => headers,
+ :status => response.status.to_s,
+ :message => ""
+ end
+
+ def client_timeout_exception_class
+ Excon::Errors::Timeout
+ end
+
+ def connection_refused_exception_class
+ Excon::Errors::SocketError
+ end
+
+ def http_library
+ :excon
+ end
+
+end
View
3  spec/acceptance/shared/callbacks.rb
@@ -87,7 +87,8 @@
it "should pass real response to callback with status and message" do
# not supported by em-http-request, it always returns "unknown" for http_reason
- unless http_library == :em_http_request
+ # not supported by excon, it only returns a status code
+ unless [:em_http_request, :excon].include?(http_library)
@response.status[0].should == 302
@response.status[1].should == "Found"
end
View
1  spec/acceptance/shared/request_expectations.rb
@@ -412,6 +412,7 @@
describe "with authentication" do
before(:each) do
+ pending "Excon does not accept basic auth user-info in URLs" if http_library == :excon
stub_request(:any, "http://user:pass@www.example.com")
stub_request(:any, "http://user:pazz@www.example.com")
end
View
12 spec/acceptance/shared/returning_declared_responses.rb
@@ -76,7 +76,8 @@ class MyException < StandardError; end;
stub_request(:get, "www.example.com").to_return(:status => [500, "Internal Server Error"])
response = http_request(:get, "http://www.example.com/")
# not supported by em-http-request, it always returns "unknown" for http_reason
- unless http_library == :em_http_request
+ # not supported by excon, it only returns a status code
+ unless [:em_http_request, :excon].include?(http_library)
response.message.should == "Internal Server Error"
end
end
@@ -90,7 +91,8 @@ class MyException < StandardError; end;
stub_request(:get, "www.example.com")
response = http_request(:get, "http://www.example.com/")
# not supported by em-http-request, it always returns "unknown" for http_reason
- unless http_library == :em_http_request
+ # not supported by excon, it only returns a status code
+ unless [:em_http_request, :excon].include?(http_library)
response.message.should == ""
end
end
@@ -188,7 +190,8 @@ def call(request)
it "should return recorded status message" do
# not supported by em-http-request, it always returns "unknown" for http_reason
- unless http_library == :em_http_request
+ # not supported by excon, it only returns a status code
+ unless [:em_http_request, :excon].include?(http_library)
@response.message.should == "OK"
end
end
@@ -225,7 +228,8 @@ def call(request)
it "should return recorded status message" do
# not supported by em-http-request, it always returns "unknown" for http_reason
- unless http_library == :em_http_request
+ # not supported by excon, it only returns a status code
+ unless [:em_http_request, :excon].include?(http_library)
@response.message.should == "OK"
end
end
View
4 spec/acceptance/shared/stubbing_requests.rb
@@ -260,6 +260,10 @@
end
describe "when stubbing request with basic authentication" do
+ before do
+ pending "Excon does not accept basic auth user-info in URLs" if http_library == :excon
+ end
+
it "should match if credentials are the same" do
stub_request(:get, "user:pass@www.example.com")
http_request(:get, "http://user:pass@www.example.com/").status.should == "200"
View
1  webmock.gemspec
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'em-synchrony', '>= 1.0.0' if RUBY_VERSION >= "1.9"
s.add_development_dependency 'curb', '>= 0.8.0'
s.add_development_dependency 'typhoeus', '>= 0.3.0' unless RUBY_PLATFORM =~ /java/
+ s.add_development_dependency 'excon', '>= 0.9.5'
s.add_development_dependency 'minitest', '>= 2.2.2'
s.add_development_dependency 'rdoc', ((RUBY_VERSION == '1.8.6') ? '<= 3.5.0' : '>3.5.0')
Please sign in to comment.
Something went wrong with that request. Please try again.