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