lib/excon/hypermedia/middlewares/hypertext_cache_pattern.rb in excon-hypermedia-0.5.2 vs lib/excon/hypermedia/middlewares/hypertext_cache_pattern.rb in excon-hypermedia-0.5.3
- old
+ new
@@ -13,40 +13,71 @@
attr_reader :datum
def request_call(datum)
@datum = datum
- return super unless datum[:hcp] == true && datum[:method] == :get && resource
+ if stubs.any?
+ # We've created new stubs. The request should be marked as `mocked`
+ # to make sure the stubbed response is returned.
+ datum[:mock] = true
- datum[:response] = {
- body: resource.to_json,
- hcp: true,
- headers: content_type_header,
- remote_ip: '127.0.0.1',
- status: 200
- }
+ # The requested resource might not be part of the embedded resources
+ # so we allow external requests.
+ # datum[:allow_unstubbed_requests] = true
+ # Make sure Excon's `Mock` middleware runs after this middleware, as
+ # it might have already triggered in the middleware chain.
+ orig_stack = @stack
+ @stack = Excon::Middleware::Mock.new(orig_stack)
+ end
+
super
+ rescue => e
+ raise unless e.class == Excon::Errors::StubNotFound
+
+ # If a request was made to a non-stubbed resource, don't use the Mock
+ # middleware, but simply send the request to the server.
+ @stack = orig_stack
+ super
end
+ def response_call(datum)
+ @datum = datum
+
+ # After the response is returned, remove any request-specific stubs
+ # from Excon, so they can't be accidentally re-used anymore.
+ embedded.each { |r| (match = matcher(r)) && Excon.unstub(match) }
+
+ super
+ end
+
private
- def resource
- @resource ||= embedded.find { |name, _| name == relation_name }.to_a[1]
+ def stubs
+ embedded.each { |r| (match = matcher(r)) && Excon.stub(match, response(r)) }.compact
end
- def relation_name
- datum.dig(:hcp_params, :relation)
+ def matcher(resource)
+ return unless (uri = ::Addressable::URI.parse(resource.dig('_links', 'self', 'href')))
+
+ {
+ scheme: uri.scheme,
+ host: uri.host,
+ path: uri.path,
+ query: uri.query
+ }
end
- def embedded
- datum.dig(:hcp_params, :embedded).to_h
+ def response(resource)
+ {
+ body: resource.to_json,
+ hcp: true,
+ headers: { 'Content-Type' => 'application/hal+json', 'X-HCP' => 'true' }
+ }
end
- def content_type_header
- return {} unless (header = datum.dig(:hcp_params, :content_type))
-
- { 'Content-Type' => header }
+ def embedded
+ datum[:embedded].to_h.values.flatten
end
end
end
end
end