lib/vcr/request_handler.rb
module VCR
# @private
class RequestHandler
include Logger::Mixin
def handle
log "Handling request: #{request_summary} (disabled: #{disabled?})"
invoke_before_request_hook
req_type = request_type(:consume_stub)
log "Identified request type (#{req_type}) for #{request_summary}"
# The before_request hook can change the type of request
# (i.e. by inserting a cassette), so we need to query the
# request type again.
#
# Likewise, the main handler logic can modify what
# #request_type would return (i.e. when a response stub is
# used), so we need to store the request type for the
# after_request hook.
set_typed_request_for_after_hook(req_type)
send "on_#{req_type}_request"
end
private
def set_typed_request_for_after_hook(request_type)
@after_hook_typed_request = Request::Typed.new(vcr_request, request_type)
end
def request_type(consume_stub = false)
case
when externally_stubbed? then :externally_stubbed
when should_ignore? then :ignored
when has_response_stub?(consume_stub) then :stubbed_by_vcr
when VCR.real_http_connections_allowed? then :recordable
else :unhandled
end
end
def invoke_before_request_hook
return if disabled? || !VCR.configuration.has_hooks_for?(:before_http_request)
typed_request = Request::Typed.new(vcr_request, request_type)
VCR.configuration.invoke_hook(:before_http_request, typed_request)
end
def invoke_after_request_hook(vcr_response)
return if disabled?
VCR.configuration.invoke_hook(:after_http_request, @after_hook_typed_request, vcr_response)
end
def externally_stubbed?
false
end
def should_ignore?
disabled? || VCR.request_ignorer.ignore?(vcr_request)
end
def disabled?
VCR.library_hooks.disabled?(library_name)
end
def has_response_stub?(consume_stub)
if consume_stub
stubbed_response
else
VCR.http_interactions.has_interaction_matching?(vcr_request)
end
end
def stubbed_response
@stubbed_response ||= VCR.http_interactions.response_for(vcr_request)
end
def library_name
# extracts `:typhoeus` from `VCR::LibraryHooks::Typhoeus::RequestHandler`
@library_name ||= self.class.name.split('::')[-2].downcase.to_sym
end
# Subclasses can implement these
def on_externally_stubbed_request
end
def on_ignored_request
end
def on_stubbed_by_vcr_request
end
def on_recordable_request
end
def on_unhandled_request
raise VCR::Errors::UnhandledHTTPRequestError.new(vcr_request)
end
def request_summary
request_matchers = if cass = VCR.current_cassette
cass.match_requests_on
else
VCR.configuration.default_cassette_options[:match_requests_on]
end
super(vcr_request, request_matchers)
end
def log_prefix
"[#{library_name}] "
end
end
end