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
|
require 'vcr/util/version_checker'
require 'vcr/request_handler'
require 'typhoeus'
if Float(Typhoeus::VERSION[/^\d+\.\d+/]) < 0.5
require 'vcr/library_hooks/typhoeus_0.4'
else
VCR::VersionChecker.new('Typhoeus', Typhoeus::VERSION, '0.5.0').check_version!
module VCR
class LibraryHooks
# @private
module Typhoeus
# @private
class RequestHandler < ::VCR::RequestHandler
attr_reader :request
def initialize(request)
@request = request
request.block_connection = false if VCR.turned_on?
end
def vcr_request
@vcr_request ||= VCR::Request.new \
request.options.fetch(:method, :get),
request.url,
request_body,
request.options.fetch(:headers, {})
end
private
def externally_stubbed?
::Typhoeus::Expectation.find_by(request)
end
def set_typed_request_for_after_hook(*args)
super
request.instance_variable_set(:@__typed_vcr_request, @after_hook_typed_request)
end
def on_unhandled_request
invoke_after_request_hook(nil)
super
end
def on_stubbed_by_vcr_request
response = ::Typhoeus::Response.new \
:http_version => stubbed_response.http_version,
:code => stubbed_response.status.code,
:status_message => stubbed_response.status.message,
:headers => stubbed_response_headers,
:body => stubbed_response.body,
:effective_url => stubbed_response.adapter_metadata.fetch('effective_url', request.url),
:mock => true
first_header_line = "HTTP/#{stubbed_response.http_version} #{response.code} #{response.status_message}\r\n"
response.instance_variable_set(:@first_header_line, first_header_line)
response.instance_variable_get(:@options)[:response_headers] =
first_header_line + response.headers.map { |k,v| "#{k}: #{v}"}.join("\r\n")
response
end
def stubbed_response_headers
@stubbed_response_headers ||= {}.tap do |hash|
stubbed_response.headers.each do |key, values|
hash[key] = values.size == 1 ? values.first : values
end if stubbed_response.headers
end
end
if ::Typhoeus::Request.method_defined?(:encoded_body)
def request_body
request.encoded_body
end
else
def request_body
request.options.fetch(:body, "")
end
end
end
# @private
class << self
def vcr_response_from(response)
VCR::Response.new \
VCR::ResponseStatus.new(response.code, response.status_message),
response.headers,
response.body,
response.http_version,
{ "effective_url" => response.effective_url }
end
def collect_chunks(request)
chunks = ''
request.on_body.unshift(
Proc.new do |body, response|
chunks += body
request.instance_variable_set(:@chunked_body, chunks)
end
)
end
def restore_body_from_chunks(response, request)
response.options[:response_body] = request.instance_variable_get(:@chunked_body)
end
end
::Typhoeus.on_complete do |response|
request = response.request
restore_body_from_chunks(response, request) if request.streaming?
unless VCR.library_hooks.disabled?(:typhoeus)
vcr_response = vcr_response_from(response)
typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
unless request.response.mock
http_interaction = VCR::HTTPInteraction.new(typed_vcr_request, vcr_response)
VCR.record_http_interaction(http_interaction)
end
VCR.configuration.invoke_hook(:after_http_request, typed_vcr_request, vcr_response)
end
end
::Typhoeus.before do |request|
collect_chunks(request) if request.streaming?
if response = VCR::LibraryHooks::Typhoeus::RequestHandler.new(request).handle
request.on_headers.each { |cb| cb.call(response) }
request.on_body.each { |cb| cb.call(response.body, response) }
request.finish(response)
else
true
end
end
end
end
end
end
VCR.configuration.after_library_hooks_loaded do
# ensure WebMock's Typhoeus adapter does not conflict with us here
# (i.e. to double record requests or whatever).
if defined?(WebMock::HttpLibAdapters::TyphoeusAdapter)
WebMock::HttpLibAdapters::TyphoeusAdapter.disable!
end
end
|