Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

254 lines (209 sloc) 6.824 kB
begin
require 'curb'
rescue LoadError
# curb not found
end
if defined?(Curl)
WebMock::VersionChecker.new('Curb', Gem.loaded_specs['curb'].version.to_s, '0.7.16').check_version!
module WebMock
module HttpLibAdapters
class CurbAdapter < HttpLibAdapter
adapter_for :curb
OriginalCurlEasy = Curl::Easy unless const_defined?(:OriginalCurlEasy)
def self.enable!
Curl.send(:remove_const, :Easy)
Curl.send(:const_set, :Easy, Curl::WebMockCurlEasy)
end
def self.disable!
Curl.send(:remove_const, :Easy)
Curl.send(:const_set, :Easy, OriginalCurlEasy)
end
# Borrowed from Patron:
# http://github.com/toland/patron/blob/master/lib/patron/response.rb
def self.parse_header_string(header_string)
status, headers = nil, {}
header_string.split(/\r\n/).each do |header|
if header =~ %r|^HTTP/1.[01] \d\d\d (.*)|
status = $1
else
parts = header.split(':', 2)
unless parts.empty?
parts[1].strip! unless parts[1].nil?
if headers.has_key?(parts[0])
headers[parts[0]] = [headers[parts[0]]] unless headers[parts[0]].kind_of? Array
headers[parts[0]] << parts[1]
else
headers[parts[0]] = parts[1]
end
end
end
end
return status, headers
end
end
end
end
module Curl
class WebMockCurlEasy < Curl::Easy
def curb_or_webmock
request_signature = build_request_signature
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
if webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
build_curb_response(webmock_response)
WebMock::CallbackRegistry.invoke_callbacks(
{:lib => :curb}, request_signature, webmock_response)
invoke_curb_callbacks
true
elsif WebMock.net_connect_allowed?(request_signature.uri)
res = yield
if WebMock::CallbackRegistry.any_callbacks?
webmock_response = build_webmock_response
WebMock::CallbackRegistry.invoke_callbacks(
{:lib => :curb, :real_request => true}, request_signature,
webmock_response)
end
res
else
raise WebMock::NetConnectNotAllowedError.new(request_signature)
end
end
def build_request_signature
method = @webmock_method.to_s.downcase.to_sym
uri = WebMock::Util::URI.heuristic_parse(self.url)
uri.path = uri.normalized_path.gsub("[^:]//","/")
uri.user = self.username
uri.password = self.password
request_body = case method
when :post
self.post_body || @post_body
when :put
@put_data
else
nil
end
request_signature = WebMock::RequestSignature.new(
method,
uri.to_s,
:body => request_body,
:headers => self.headers
)
request_signature
end
def build_curb_response(webmock_response)
raise Curl::Err::TimeoutError if webmock_response.should_timeout
webmock_response.raise_error_if_any
@body_str = webmock_response.body
@response_code = webmock_response.status[0]
@header_str = "HTTP/1.1 #{webmock_response.status[0]} #{webmock_response.status[1]}\r\n"
if webmock_response.headers
@header_str << webmock_response.headers.map do |k,v|
"#{k}: #{v.is_a?(Array) ? v.join(", ") : v}"
end.join("\r\n")
location = webmock_response.headers['Location']
if self.follow_location? && location
@last_effective_url = location
webmock_follow_location(location)
end
@content_type = webmock_response.headers["Content-Type"]
end
@last_effective_url ||= self.url
end
def webmock_follow_location(location)
first_url = self.url
self.url = location
curb_or_webmock do
send( "http_#{@webmock_method}_without_webmock" )
end
self.url = first_url
end
def invoke_curb_callbacks
@on_progress.call(0.0,1.0,0.0,1.0) if @on_progress
@on_header.call(self.header_str) if @on_header
@on_body.call(self.body_str) if @on_body
@on_complete.call(self) if @on_complete
case response_code
when 200..299
@on_success.call(self) if @on_success
when 400..599
@on_failure.call(self, self.response_code) if @on_failure
end
end
def build_webmock_response
status, headers =
WebMock::HttpLibAdapters::CurbAdapter.parse_header_string(self.header_str)
webmock_response = WebMock::Response.new
webmock_response.status = [self.response_code, status]
webmock_response.body = self.body_str
webmock_response.headers = headers
webmock_response
end
###
### Mocks of Curl::Easy methods below here.
###
def http(method)
@webmock_method = method
super
end
%w[ get head delete ].each do |verb|
define_method "http_#{verb}" do
@webmock_method = verb
super()
end
end
def http_put data = nil
@webmock_method = :put
@put_data = data if data
super
end
def http_post *data
@webmock_method = :post
@post_body = data.join('&') if data && !data.empty?
super
end
def perform
@webmock_method ||= :get
curb_or_webmock { super }
end
def put_data= data
@webmock_method = :put
@put_data = data
super
end
def post_body= data
@webmock_method = :post
super
end
def delete= value
@webmock_method = :delete if value
super
end
def head= value
@webmock_method = :head if value
super
end
def body_str
@body_str || super
end
def response_code
@response_code || super
end
def header_str
@header_str || super
end
def last_effective_url
@last_effective_url || super
end
def content_type
@content_type || super
end
%w[ success failure header body complete progress ].each do |callback|
class_eval <<-METHOD, __FILE__, __LINE__
def on_#{callback} &block
@on_#{callback} = block
super
end
METHOD
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.