Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

HTTP Gem support #356

Merged
merged 1 commit into from

2 participants

@ixti

No description provided.

@ixti

Just to inform. Build is broken because of excon adapter. If you will merge my PR (#357) for excon adapter this build will pass too.

@bblimke
Owner

Very nice and clean code. Great work. Thanks!

@bblimke bblimke merged commit e0f9382 into from
@ixti

WooHoo! Thanks!

@ixti ixti deleted the branch
@bblimke
Owner

Released as 1.17.0

@ixti

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 12, 2014
  1. @ixti

    HTTP Gem support

    ixti authored
This page is out of date. Refresh to see the latest.
View
1  README.md
@@ -25,6 +25,7 @@ Supported HTTP libraries
* Curb (currently only Curb::Easy)
* Typhoeus (currently only Typhoeus::Hydra)
* Excon
+* HTTP Gem
Supported Ruby Interpreters
---------------------------
View
1  lib/webmock.rb
@@ -38,6 +38,7 @@
require 'webmock/http_lib_adapters/http_lib_adapter_registry'
require 'webmock/http_lib_adapters/http_lib_adapter'
require 'webmock/http_lib_adapters/net_http'
+require 'webmock/http_lib_adapters/http_gem_adapter'
require 'webmock/http_lib_adapters/httpclient_adapter'
require 'webmock/http_lib_adapters/patron_adapter'
require 'webmock/http_lib_adapters/curb_adapter'
View
170 lib/webmock/http_lib_adapters/http_gem_adapter.rb
@@ -0,0 +1,170 @@
+begin
+ require "http"
+rescue LoadError
+ # HTTP gem not found
+end
+
+
+if defined?(HTTP::Client)
+ module WebMock
+ module HttpLibAdapters
+ class HttpGemAdapter < HttpLibAdapter
+
+ adapter_for :http_gem
+
+
+ def self.enable!
+ ::HTTP.enable_webmock!
+ end
+
+
+ def self.disable!
+ ::HTTP.disable_webmock!
+ end
+
+ end
+ end
+ end
+
+
+ module HTTP
+ class Request
+
+ def webmock_signature
+ ::WebMock::RequestSignature.new(method, uri.to_s, {
+ :headers => headers,
+ :body => body
+ })
+ end
+
+ end
+
+
+ class Response
+
+ def to_webmock
+ webmock_response = ::WebMock::Response.new
+
+ webmock_response.status = [status, reason]
+ webmock_response.body = body
+ webmock_response.headers = headers
+
+ webmock_response
+ end
+
+
+ def self.from_webmock(webmock_response)
+ status = webmock_response.status.first
+ headers = webmock_response.headers || {}
+ body = webmock_response.body
+
+ new(status, "1.1", headers, body)
+ end
+
+ end
+
+
+ class WebMockPerform
+
+ def initialize request, &perform
+ @request = request
+ @perform = perform
+ end
+
+
+ def exec
+ replay || perform || halt
+ end
+
+
+ def request_signature
+ unless @request_signature
+ @request_signature = @request.webmock_signature
+ register_request(@request_signature)
+ end
+
+ @request_signature
+ end
+
+
+ protected
+
+
+ def response_for_request(signature)
+ ::WebMock::StubRegistry.instance.response_for_request(signature)
+ end
+
+
+ def register_request(signature)
+ ::WebMock::RequestRegistry.instance.requested_signatures.put(signature)
+ end
+
+
+ def replay
+ webmock_response = response_for_request(request_signature)
+
+ return unless webmock_response
+
+ raise Errno::ETIMEDOUT if webmock_response.should_timeout
+ webmock_response.raise_error_if_any
+
+ invoke_callbacks(webmock_response, :real_request => false)
+ ::HTTP::Response.from_webmock webmock_response
+ end
+
+
+ def perform
+ return unless ::WebMock.net_connect_allowed?(request_signature.uri)
+ response = @perform.call
+ invoke_callbacks(response.to_webmock, :real_request => true)
+ response
+ end
+
+
+ def halt
+ raise ::WebMock::NetConnectNotAllowedError.new request_signature
+ end
+
+
+ def invoke_callbacks webmock_response, options = {}
+ ::WebMock::CallbackRegistry.invoke_callbacks(
+ options.merge({ :lib => :http_gem }),
+ request_signature,
+ webmock_response
+ )
+ end
+
+ end
+
+
+ class Client
+
+ alias :__perform__ :perform
+
+ def perform request, options
+ return __perform__(request, options) unless ::HTTP.webmock_enabled?
+ WebMockPerform.new(request) { __perform__(request, options) }.exec
+ end
+
+ end
+
+
+ class << self
+
+ def enable_webmock!
+ @webmock_enabled = true
+ end
+
+
+ def disable_webmock!
+ @webmock_enabled = false
+ end
+
+
+ def webmock_enabled?
+ @webmock_enabled
+ end
+
+ end
+ end
+end
View
54 spec/acceptance/http_gem/http_gem_spec.rb
@@ -0,0 +1,54 @@
+# encoding: utf-8
+
+require "spec_helper"
+require "acceptance/webmock_shared"
+require "acceptance/http_gem/http_gem_spec_helper"
+
+describe "HTTP Gem" do
+
+ include HttpGemSpecHelper
+
+
+ include_examples "with WebMock", :no_status_message
+
+
+ context "when not following redirects" do
+
+ let(:response) { http_request(:get, "http://example.com") }
+ let(:headers) { response.headers }
+
+ it "stops on first request" do
+ stub_simple_request("example.com", 302, "Location" => "www.example.com")
+ stub_simple_request("www.example.com")
+
+ expect(headers).to include "Host" => "example.com"
+ end
+
+ end
+
+
+ context "when following redirects" do
+
+ let(:response) { http_request(:get, "http://example.com", :follow => true) }
+ let(:headers) { response.headers }
+
+
+ it "returns response of destination" do
+ stub_simple_request("example.com", 302, "Location" => "www.example.com")
+ stub_simple_request("www.example.com")
+
+ expect(headers).to include "Host" => "www.example.com"
+ end
+
+
+ it "works with more than one redirect" do
+ stub_simple_request("example.com", 302, "Location" => "www.example.com")
+ stub_simple_request("www.example.com", 302, "Location" => "blog.example.com")
+ stub_simple_request("blog.example.com")
+
+ expect(headers).to include "Host" => "blog.example.com"
+ end
+
+ end
+
+end
View
52 spec/acceptance/http_gem/http_gem_spec_helper.rb
@@ -0,0 +1,52 @@
+require "ostruct"
+
+
+module HttpGemSpecHelper
+
+ def http_request(method, uri, options = {}, &block)
+ response = HTTP.request(method, normalize_uri(uri), options).response
+
+ OpenStruct.new({
+ :body => response.body,
+ :headers => normalize_headers(response.headers),
+ :status => response.status.to_s,
+ :message => response.reason
+ })
+ end
+
+
+ def normalize_uri(uri)
+ Addressable::URI.heuristic_parse(uri).normalize.to_s
+ end
+
+
+ def normalize_headers headers
+ WebMock::Util::Headers.normalize_headers(Hash[headers.map { |k, v|
+ [k, v.is_a?(Array) ? v.join(", ") : v]
+ }])
+ end
+
+
+ def stub_simple_request host, status = 200, headers = {}
+ stub_request(:any, host).to_return({
+ :status => status,
+ :headers => headers.merge({ "Host" => host })
+ })
+ end
+
+
+ def client_timeout_exception_class
+ Errno::ETIMEDOUT
+ end
+
+
+ def connection_refused_exception_class
+ Errno::ECONNREFUSED
+ end
+
+
+ def http_library
+ :http_gem
+ end
+
+end
View
1  webmock.gemspec
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
s.add_dependency 'crack', '>=0.3.2'
s.add_development_dependency 'rspec', '~> 2.10'
+ s.add_development_dependency 'http', '>= 0.5.0'
s.add_development_dependency 'httpclient', '>= 2.2.4'
s.add_development_dependency 'patron', '>= 0.4.18' unless RUBY_PLATFORM =~ /java/
s.add_development_dependency 'em-http-request', '>= 1.0.2'
Something went wrong with that request. Please try again.