Class: Heroics::Link
- Inherits:
-
Object
- Object
- Heroics::Link
- Defined in:
- lib/heroics/link.rb
Overview
A link invokes requests with an HTTP server.
Defined Under Namespace
Classes: CachedResponse
Instance Method Summary collapse
-
#initialize(url, link_schema, options = {}) ⇒ Link
constructor
Instantiate a link.
-
#run(*parameters) ⇒ String, ...
Make a request to the server.
Constructor Details
#initialize(url, link_schema, options = {}) ⇒ Link
Instantiate a link.
16 17 18 19 20 21 22 23 |
# File 'lib/heroics/link.rb', line 16 def initialize(url, link_schema, ={}) @root_url, @path_prefix = unpack_url(url) @link_schema = link_schema @default_headers = [:default_headers] || {} @cache = [:cache] || {} @rate_throttle = [:rate_throttle] || Heroics::Configuration.defaults.[:rate_throttle] @status_codes = [:status_codes] || Heroics::Configuration.defaults.[:status_codes] end |
Instance Method Details
#run(*parameters) ⇒ String, ...
Make a request to the server.
JSON content received with an ETag is cached. When the server returns a *304 Not Modified* status code content is loaded and returned from the cache. The cache considers headers, in addition to the URL path, when creating keys so that requests to the same path, such as for paginated results, don’t cause cache collisions.
When the server returns a *206 Partial Content* status code the result is assumed to be an array and an enumerator is returned. The enumerator yields results from the response until they’ve been consumed at which point, if additional content is available from the server, it blocks and makes a request to fetch the subsequent page of data. This behaviour continues until the client stops iterating the enumerator or the dataset from the server has been entirely consumed.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/heroics/link.rb', line 48 def run(*parameters) path, body = @link_schema.format_path(parameters) path = "#{@path_prefix}#{path}" unless @path_prefix == '/' headers = @default_headers if body case @link_schema.method when :put, :post, :patch headers = headers.merge({'Content-Type' => @link_schema.content_type}) body = @link_schema.encode(body) when :get, :delete if body.is_a?(Hash) query = body else query = MultiJson.load(body) end body = nil end end connection = Excon.new(@root_url, thread_safe_sockets: true) response = request_with_cache(connection, method: @link_schema.method, path: path, headers: headers, body: body, query: query, expects: [200, 201, 202, 204, 206]) content_type = response.headers['Content-Type'] if content_type && content_type =~ /application\/.*json/ body = MultiJson.load(response.body) if response.status == 206 next_range = response.headers['Next-Range'] Enumerator.new do |yielder| while true do # Yield the results we got in the body. body.each do |item| yielder << item end # Only make a request to get the next page if we have a valid # next range. break unless next_range headers = headers.merge({'Range' => next_range}) response = request_with_cache(connection, method: @link_schema.method, path: path, headers: headers, expects: [200, 201, 206]) body = MultiJson.load(response.body) next_range = response.headers['Next-Range'] end end else body end elsif !response.body.empty? response.body end end |