module JsonApiClient
TODO: conform to JSON API spec v1.0 jsonapi.org
Public Class Methods
fetch_all_pages(url:)
click to toggle source
Fetches all pages for the given url. Information about pagination is provided in the Link header of an API call. tools.ietf.org/html/rfc5988 Example: Link: <api.github.com/search/code?q=addClass+user%3Amozilla&page=2>; rel=“next”
<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last"
Returns JSON parsed response body
# File lib/json_api_client.rb, line 18 def JsonApiClient.fetch_all_pages(url:) headers, body = fetch_page(url: url) return nil if headers.nil? || body.nil? resources = JSON.parse(body) while url = next_page(headers: headers) do headers, body = fetch_page(url: url) resources << JSON.parse(body) end resources end
fetch_page(url:)
click to toggle source
Fetches a single page for the given url.
Returns a header, body pair of response
# File lib/json_api_client.rb, line 35 def JsonApiClient.fetch_page(url:) begin res = open(URI(url)) [res.meta, res.read] rescue OpenURI::HTTPError => e process_error e end end
next_page(headers:)
click to toggle source
Finds next page from ‘Link’ response header
Returns a url of next page
# File lib/json_api_client.rb, line 81 def JsonApiClient.next_page(headers:) link = (headers["Link"] || "").split(', ').map do |link| href, name = link.match(/<(.*?)>; rel="(\w+)"/).captures return href if name == 'next' end nil end
process_error(error)
click to toggle source
Abstract OpenURI::HTTPErrors so we can:
-
provide more information
-
replace it later if needed
Raises new error containing any additional valuable information.
# File lib/json_api_client.rb, line 49 def JsonApiClient.process_error(error) headers = error.io.meta if error.message == '404 Not Found' raise JsonApiClient::NotFound.new(headers: headers, message: 'Not Found') elsif error.message == '403 Forbidden' # Rate Limit Remaining examples: http://stackoverflow.com/a/16022625 ratelimit_remaining = headers["x-ratelimit-userremaining"] || headers["x-ratelimit-remaining"] || headers["x-rate-limit-remaining"] if ratelimit_remaining.to_i == 0 ratelimit_reset = headers["x-ratelimit-reset"] || headers["x-rate-limit-reset"] || headers["x-ratelimit-userreset"] message = 'Rate limit exceeded.' if ratelimit_reset ratelimit_reset_time = Time.at(ratelimit_reset.to_i) message += " Try again after #{ratelimit_reset_time}." end api_error = JsonApiClient::RateLimitExceeded.new(headers: headers, message: message) raise api_error end end raise JsonApiClient::Error.new(headers: headers, message: error.message) end