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