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