lib/zooming-proxy/middleware.rb in zooming-proxy-0.1.0 vs lib/zooming-proxy/middleware.rb in zooming-proxy-0.2.0

- old
+ new

@@ -1,9 +1,12 @@ # frozen_string_literal: true require 'json' +require 'typhoeus' +Typhoeus::Config.memoize = true + module ZoomingProxy # Middleware # class Middleware attr_reader :host, :scheme, :forwarded @@ -57,40 +60,48 @@ body = response_to_hash(response) return zoomed_response(status, headers, body, depth) unless zoomable?(headers, body, depth) body['_embedded'] ||= {} headers['X-HAL-Zooming'] = depth + body = parallel_zooms(body, headers, depth) - requested_links(body, headers).each { |link| body = zoom_rel(headers, body, depth, link) } zoomed_response(status, headers, body, depth) end - def zoom_rel(headers, body, depth, link) - relation, hrefs = link - array = hrefs.respond_to?(:to_ary) + def parallel_zooms(body, headers, depth) + hydra = Typhoeus::Hydra.new + requested_links(body, headers).map do |url, attributes| + request = request_rel(url, headers) + request.on_complete do |res| + body = zoom_rel(attributes[:relation], res, body, attributes[:array], depth) + end + hydra.queue(request) + end + hydra.run - [*hrefs].each do |href| - res = request_rel(href, headers) - embedded_body = handle_nested_embeds(res, depth) + body + end - if array - body['_embedded'][relation] ||= [] - body['_embedded'][relation] << embedded_body - else - body['_embedded'][relation] = embedded_body - end + def zoom_rel(relation, response, body, array, depth) + embedded_body = handle_nested_embeds(response, depth) + + if array + body['_embedded'][relation] ||= [] + body['_embedded'][relation] << embedded_body + else + body['_embedded'][relation] = embedded_body end body end def request_rel(href, headers) uri = URI.parse(href) uri.scheme = scheme uri.host = host - Typhoeus.get(uri, headers: headers) + Typhoeus::Request.new(uri, headers: headers) end def response_to_hash(response) response = response.to_json if response.respond_to?(:each_key) @@ -124,18 +135,16 @@ zoomable && !body.nil? end def requested_links(body, headers) - links = requested_zooms(headers).select { |rel| body['_links'].key?(rel) } - links.map do |rel| - link = body['_links'][rel] + body['_links'] + .to_h + .select { |k, _| headers['x-hal-zoom'].split(/\s+/).include?(k) } + .each_with_object({}) do |(k, v), urls| + array = v.respond_to?(:to_ary) - [rel, link.respond_to?(:to_ary) ? link.map { |l| l['href'] } : link['href']] - end - end - - def requested_zooms(headers) - headers['x-hal-zoom'].split(/\s+/) + [v].flatten.each { |url| urls[url['href']] = { relation: k, array: array } } + end end end end