lib/httpx/adapters/webmock.rb in httpx-0.18.3 vs lib/httpx/adapters/webmock.rb in httpx-0.18.4

- old
+ new

@@ -14,60 +14,12 @@ # HTTPX plugin for webmock. # # Requests are "hijacked" at the session, before they're distributed to a connection. # module Plugin - module InstanceMethods - private - - def send_requests(*requests) - request_signatures = requests.map do |request| - request_signature = _build_webmock_request_signature(request) - WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) - request_signature - end - - responses = request_signatures.map do |request_signature| - WebMock::StubRegistry.instance.response_for_request(request_signature) - end - - real_requests = {} - - requests.each_with_index.each_with_object([request_signatures, responses]) do |(request, idx), (sig_reqs, mock_responses)| - if (webmock_response = mock_responses[idx]) - mock_responses[idx] = _build_from_webmock_response(request, webmock_response) - WebMock::CallbackRegistry.invoke_callbacks({ lib: :httpx }, sig_reqs[idx], webmock_response) - log { "mocking #{request.uri} with #{mock_responses[idx].inspect}" } - elsif WebMock.net_connect_allowed?(sig_reqs[idx].uri) - log { "performing #{request.uri}" } - real_requests[request] = idx - else - raise WebMock::NetConnectNotAllowedError, sig_reqs[idx] - end - end - - unless real_requests.empty? - reqs = real_requests.keys - reqs.zip(super(*reqs)).each do |req, res| - idx = real_requests[req] - - if WebMock::CallbackRegistry.any_callbacks? - webmock_response = _build_webmock_response(req, res) - WebMock::CallbackRegistry.invoke_callbacks( - { lib: :httpx, real_request: true }, request_signatures[idx], - webmock_response - ) - end - - responses[idx] = res - end - end - - responses - end - - def _build_webmock_request_signature(request) + class << self + def build_webmock_request_signature(request) uri = WebMock::Util::URI.heuristic_parse(request.uri) uri.path = uri.normalized_path.gsub("[^:]//", "/") WebMock::RequestSignature.new( request.verb, @@ -75,47 +27,107 @@ body: request.body.each.to_a.join, headers: request.headers.to_h ) end - def _build_webmock_response(_request, response) + def build_webmock_response(_request, response) webmock_response = WebMock::Response.new webmock_response.status = [response.status, HTTP_REASONS[response.status]] webmock_response.body = response.body.to_s webmock_response.headers = response.headers.to_h webmock_response end - def _build_from_webmock_response(request, webmock_response) - return _build_error_response(request, HTTPX::TimeoutError.new(1, "Timed out")) if webmock_response.should_timeout + def build_from_webmock_response(request, webmock_response) + return build_error_response(request, HTTPX::TimeoutError.new(1, "Timed out")) if webmock_response.should_timeout - return _build_error_response(request, webmock_response.exception) if webmock_response.exception + return build_error_response(request, webmock_response.exception) if webmock_response.exception response = request.options.response_class.new(request, webmock_response.status[0], "2.0", webmock_response.headers) response << webmock_response.body.dup response end - def _build_error_response(request, exception) + def build_error_response(request, exception) HTTPX::ErrorResponse.new(request, exception, request.options) end end + + module InstanceMethods + def build_connection(*) + connection = super + connection.once(:unmock_connection) do + pool.__send__(:resolve_connection, connection) + pool.__send__(:unregister_connection, connection) unless connection.addresses + end + connection + end + end + + module ConnectionMethods + def initialize(*) + super + @mocked = true + end + + def open? + return true if @mocked + + super + end + + def interests + return if @mocked + + super + end + + def send(request) + request_signature = Plugin.build_webmock_request_signature(request) + WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) + + if (mock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)) + response = Plugin.build_from_webmock_response(request, mock_response) + WebMock::CallbackRegistry.invoke_callbacks({ lib: :httpx }, request_signature, mock_response) + log { "mocking #{request.uri} with #{mock_response.inspect}" } + request.response = response + request.emit(:response, response) + elsif WebMock.net_connect_allowed?(request_signature.uri) + if WebMock::CallbackRegistry.any_callbacks? + request.on(:response) do |resp| + unless resp.is_a?(HTTPX::ErrorResponse) + webmock_response = Plugin.build_webmock_response(request, resp) + WebMock::CallbackRegistry.invoke_callbacks( + { lib: :httpx, real_request: true }, request_signature, + webmock_response + ) + end + end + end + @mocked = false + emit(:unmock_connection, self) + super + else + raise WebMock::NetConnectNotAllowedError, request_signature + end + end + end end class HttpxAdapter < HttpLibAdapter adapter_for :httpx class << self def enable! - @original_session = ::HTTPX::Session + @original_session = HTTPX::Session - webmock_session = ::HTTPX.plugin(Plugin) + webmock_session = HTTPX.plugin(Plugin) - ::HTTPX.send(:remove_const, :Session) - ::HTTPX.send(:const_set, :Session, webmock_session.class) + HTTPX.send(:remove_const, :Session) + HTTPX.send(:const_set, :Session, webmock_session.class) end def disable! return unless @original_session