1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
# frozen_string_literal: true
begin
require 'typhoeus'
rescue LoadError
# typhoeus not found
end
if defined?(Typhoeus)
WebMock::VersionChecker.new('Typhoeus', Typhoeus::VERSION, '0.3.2').check_version!
module WebMock
module HttpLibAdapters
class TyphoeusAdapter < HttpLibAdapter
adapter_for :typhoeus
def self.enable!
@disabled = false
add_before_callback
add_after_request_callback
::Typhoeus::Config.block_connection = true
end
def self.disable!
@disabled = true
remove_after_request_callback
remove_before_callback
::Typhoeus::Config.block_connection = false
end
def self.disabled?
!!@disabled
end
def self.add_before_callback
unless Typhoeus.before.include?(BEFORE_CALLBACK)
Typhoeus.before << BEFORE_CALLBACK
end
end
def self.remove_before_callback
Typhoeus.before.delete_if {|v| v == BEFORE_CALLBACK }
end
def self.add_after_request_callback
unless Typhoeus.on_complete.include?(AFTER_REQUEST_CALLBACK)
Typhoeus.on_complete << AFTER_REQUEST_CALLBACK
end
end
def self.remove_after_request_callback
Typhoeus.on_complete.delete_if {|v| v == AFTER_REQUEST_CALLBACK }
end
def self.build_request_signature(req)
uri = WebMock::Util::URI.heuristic_parse(req.url)
uri.path = uri.normalized_path.gsub("[^:]//","/")
headers = req.options[:headers]
if req.options[:userpwd]
headers['Authorization'] = WebMock::Util::Headers.basic_auth_header(req.options[:userpwd])
end
body = req.options[:body]
if body.is_a?(Hash)
body = WebMock::Util::QueryMapper.values_to_query(body)
end
request_signature = WebMock::RequestSignature.new(
req.options[:method] || :get,
uri.to_s,
body: body,
headers: headers
)
req.instance_variable_set(:@__webmock_request_signature, request_signature)
request_signature
end
def self.build_webmock_response(typhoeus_response)
webmock_response = WebMock::Response.new
webmock_response.status = [typhoeus_response.code, typhoeus_response.status_message]
webmock_response.body = typhoeus_response.body
webmock_response.headers = typhoeus_response.headers
webmock_response
end
def self.generate_typhoeus_response(request_signature, webmock_response)
response = if webmock_response.should_timeout
::Typhoeus::Response.new(
code: 0,
status_message: "",
body: "",
headers: {},
return_code: :operation_timedout,
total_time: 0.0,
starttransfer_time: 0.0,
appconnect_time: 0.0,
pretransfer_time: 0.0,
connect_time: 0.0,
namelookup_time: 0.0,
redirect_time: 0.0
)
else
::Typhoeus::Response.new(
code: webmock_response.status[0],
status_message: webmock_response.status[1],
body: webmock_response.body,
headers: webmock_response.headers,
effective_url: request_signature.uri,
total_time: 0.0,
starttransfer_time: 0.0,
appconnect_time: 0.0,
pretransfer_time: 0.0,
connect_time: 0.0,
namelookup_time: 0.0,
redirect_time: 0.0
)
end
response.mock = :webmock
response
end
def self.request_hash(request_signature)
hash = {}
hash[:body] = request_signature.body
hash[:headers] = request_signature.headers
hash
end
AFTER_REQUEST_CALLBACK = Proc.new do |response|
request = response.request
request_signature = request.instance_variable_get(:@__webmock_request_signature)
webmock_response =
::WebMock::HttpLibAdapters::TyphoeusAdapter.
build_webmock_response(response)
if response.mock
WebMock::CallbackRegistry.invoke_callbacks(
{lib: :typhoeus},
request_signature,
webmock_response
)
else
WebMock::CallbackRegistry.invoke_callbacks(
{lib: :typhoeus, real_request: true},
request_signature,
webmock_response
)
end
end
BEFORE_CALLBACK = Proc.new do |request|
Typhoeus::Expectation.all.delete_if {|e| e.from == :webmock }
res = true
unless WebMock::HttpLibAdapters::TyphoeusAdapter.disabled?
request_signature = ::WebMock::HttpLibAdapters::TyphoeusAdapter.build_request_signature(request)
request.block_connection = false;
::WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
if webmock_response = ::WebMock::StubRegistry.instance.response_for_request(request_signature)
# ::WebMock::HttpLibAdapters::TyphoeusAdapter.stub_typhoeus(request_signature, webmock_response, self)
response = ::WebMock::HttpLibAdapters::TyphoeusAdapter.generate_typhoeus_response(request_signature, webmock_response)
if request.respond_to?(:on_headers)
request.execute_headers_callbacks(response)
end
if request.respond_to?(:streaming?) && request.streaming?
response.options[:response_body] = "".dup
request.on_body.each { |callback| callback.call(webmock_response.body, response) }
end
request.finish(response)
webmock_response.raise_error_if_any
res = false
elsif !WebMock.net_connect_allowed?(request_signature.uri)
raise WebMock::NetConnectNotAllowedError.new(request_signature)
end
end
res
end
end
end
end
end
|