class WCC::Contentful::SimpleClient
The SimpleClient
accesses the Contentful CDN to get JSON responses, returning the raw JSON data as a parsed hash. This is the bottom layer of the WCC::Contentful
gem.
Note: Do not create this directly, instead create one of WCC::Contentful::SimpleClient::Cdn
, WCC::Contentful::SimpleClient::Preview
, WCC::Contentful::SimpleClient::Management
It can be configured to access any API url and exposes only a single method, `get`. This method returns a WCC::Contentful::SimpleClient::Response
that handles paging automatically.
The SimpleClient
by default uses 'faraday' to perform the gets, but any HTTP client adapter be injected by passing the `connection:` option.
@api Client
Constants
- ADAPTERS
Attributes
Public Class Methods
# File lib/wcc/contentful/simple_client.rb, line 83 def self.load_adapter(adapter) case adapter when nil ADAPTERS.each do |a, spec| begin gem(*spec) return load_adapter(a) rescue Gem::LoadError next end end raise ArgumentError, 'Unable to load adapter! Please install one of '\ "#{ADAPTERS.values.map(&:join).join(',')}" when :faraday require 'faraday' ::Faraday.new do |faraday| faraday.response :logger, (Rails.logger if defined?(Rails)), { headers: false, bodies: false } faraday.adapter :net_http end when :typhoeus require_relative 'simple_client/typhoeus_adapter' TyphoeusAdapter.new else unless adapter.respond_to?(:get) raise ArgumentError, "Adapter #{adapter} is not invokeable! Please "\ "pass use one of #{ADAPTERS.keys} or create a Faraday-compatible adapter" end adapter end end
Creates a new SimpleClient
with the given configuration.
@param [String] api_url
the base URL of the Contentful API to connect to @param [String] space The Space ID to access @param [String] access_token A Contentful Access Token to be sent in the Authorization header @param [Hash] options The remaining optional parameters, defined below @option options [Symbol, Object] connection The Faraday connection to use to make requests.
Auto-discovered based on what gems are installed if this is not provided.
@option options [String] default_locale The locale query param to set by default. @option options [String] environment The contentful environment to access. Defaults to 'master'. @option options [Boolean] no_follow_redirects If true, do not follow 300 level redirects. @option options [Number] rate_limit_wait_timeout The maximum time to block the thread waiting
on a rate limit response. By default will wait for one 429 and then fail on the second 429.
# File lib/wcc/contentful/simple_client.rb, line 43 def initialize(api_url:, space:, access_token:, **options) @api_url = URI.join(api_url, '/spaces/', space + '/') @space = space @access_token = access_token @adapter = SimpleClient.load_adapter(options[:connection]) @options = options @_instrumentation = @options[:instrumentation] @query_defaults = {} @query_defaults[:locale] = @options[:default_locale] if @options[:default_locale] # default 1.5 so that we retry one time then fail if still rate limited # https://www.contentful.com/developers/docs/references/content-preview-api/#/introduction/api-rate-limits @rate_limit_wait_timeout = @options[:rate_limit_wait_timeout] || 1.5 return unless options[:environment].present? @api_url = URI.join(@api_url, 'environments/', options[:environment] + '/') end
Public Instance Methods
performs an HTTP GET request to the specified path within the configured space and environment. Query parameters are merged with the defaults and appended to the request.
# File lib/wcc/contentful/simple_client.rb, line 66 def get(path, query = {}) url = URI.join(@api_url, path) resp = _instrument 'get_http', url: url, query: query do get_http(url, query) end Response.new(self, { url: url, query: query }, resp) end
Private Instance Methods
# File lib/wcc/contentful/simple_client.rb, line 116 def _instrumentation_event_prefix # Unify all CDN, Management, Preview notifications under same namespace '.simpleclient.contentful.wcc' end
# File lib/wcc/contentful/simple_client.rb, line 121 def get_http(url, query, headers = {}) headers = { Authorization: "Bearer #{@access_token}" }.merge(headers || {}) q = @query_defaults.dup q = q.merge(query) if query start = Process.clock_gettime(Process::CLOCK_MONOTONIC) loop do resp = @adapter.get(url, q, headers) if [301, 302, 307].include?(resp.status) && !@options[:no_follow_redirects] url = resp.headers['Location'] next end if resp.status == 429 && reset = resp.headers['X-Contentful-RateLimit-Reset'].presence reset = reset.to_f _instrument 'rate_limit', start: start, reset: reset, timeout: @rate_limit_wait_timeout now = Process.clock_gettime(Process::CLOCK_MONOTONIC) if (now - start) + reset < @rate_limit_wait_timeout sleep(reset) next end end return resp end end