class Contentful::Client

The client object is initialized with a space and a key and then used for querying resources from this space. See README for details

Constants

DEFAULT_CONFIGURATION

Default configuration for Contentful::Client

Attributes

configuration[R]
logger[R]
proxy[R]

Public Class Methods

get_http(url, query, headers = {}, proxy = {}, timeout = {}) click to toggle source

Wraps the actual HTTP request via proxy @private

# File lib/contentful/client.rb, line 54
def self.get_http(url, query, headers = {}, proxy = {}, timeout = {})
  http = HTTP[headers]
  http = http.timeout(timeout) if timeout.any?
  if proxy[:host]
    http.via(proxy[:host], proxy[:port], proxy[:username], proxy[:password]).get(url, params: query)
  else
    http.get(url, params: query)
  end
end
new(given_configuration = {}) click to toggle source

@see _ github.com/contentful/contentful.rb#client-configuration-options @param [Hash] given_configuration @option given_configuration [String] :space Required @option given_configuration [String] :access_token Required @option given_configuration [String] :api_url Modifying this to ‘preview.contentful.com’ gives you access to our Preview API @option given_configuration [String] :api_version @option given_configuration [String] :default_locale @option given_configuration [String] :proxy_host @option given_configuration [String] :proxy_username @option given_configuration [String] :proxy_password @option given_configuration [Number] :proxy_port @option given_configuration [Number] :timeout_read @option given_configuration [Number] :timeout_write @option given_configuration [Number] :timeout_connect @option given_configuration [Number] :max_rate_limit_retries @option given_configuration [Number] :max_rate_limit_wait @option given_configuration [Number] :max_include_resolution_depth @option given_configuration [Boolean] :use_camel_case @option given_configuration [Boolean] :gzip_encoded @option given_configuration [Boolean] :raw_mode @option given_configuration [false, ::Logger] :logger @option given_configuration [::Logger::DEBUG, ::Logger::INFO, ::Logger::WARN, ::Logger::ERROR] :log_level @option given_configuration [Boolean] :raise_errors @option given_configuration [Boolean] :raise_for_empty_fields @option given_configuration [::Array<String>] :dynamic_entries @option given_configuration [::Hash<String, Contentful::Resource>] :resource_mapping @option given_configuration [::Hash<String, Contentful::Resource>] :entry_mapping @option given_configuration [String] :application_name @option given_configuration [String] :application_version @option given_configuration [String] :integration_name @option given_configuration [String] :integration_version

# File lib/contentful/client.rb, line 95
def initialize(given_configuration = {})
  @configuration = default_configuration.merge(given_configuration)
  normalize_configuration!
  validate_configuration!
  setup_logger

  update_dynamic_entry_cache! if configuration[:dynamic_entries] == :auto
end

Public Instance Methods

app_info() click to toggle source

Returns the X-Contentful-User-Agent app data @private

# File lib/contentful/client.rb, line 246
def app_info
  { name: configuration[:application_name], version: configuration[:application_version] }
end
asset(id, query = {}) click to toggle source

Gets a specific asset

@param [String] id @param [Hash] query

@return [Contentful::Asset]

# File lib/contentful/client.rb, line 195
def asset(id, query = {})
  Request.new(self, environment_url('/assets'), query, id).get
end
assets(query = {}) click to toggle source

Gets a collection of assets

@param [Hash] query

@return [Contentful::Array<Contentful::Asset>]

# File lib/contentful/client.rb, line 204
def assets(query = {})
  normalize_select!(query)
  Request.new(self, environment_url('/assets'), query).get
end
base_url() click to toggle source

Returns the base url for all of the client’s requests @private

# File lib/contentful/client.rb, line 220
def base_url
  "http#{configuration[:secure] ? 's' : ''}://#{configuration[:api_url]}/spaces/#{configuration[:space]}"
end
content_type(id, query = {}) click to toggle source

Gets a specific content type

@param [String] id @param [Hash] query

@return [Contentful::ContentType]

# File lib/contentful/client.rb, line 150
def content_type(id, query = {})
  Request.new(self, environment_url('/content_types'), query, id).get
end
content_types(query = {}) click to toggle source

Gets a collection of content types

@param [Hash] query

@return [Contentful::Array<Contentful::ContentType>]

# File lib/contentful/client.rb, line 159
def content_types(query = {})
  Request.new(self, environment_url('/content_types'), query).get
end
contentful_user_agent() click to toggle source

Returns the X-Contentful-User-Agent @private

# File lib/contentful/client.rb, line 275
def contentful_user_agent
  header = {
    'sdk' => sdk_info,
    'app' => app_info,
    'integration' => integration_info,
    'platform' => platform_info,
    'os' => os_info
  }

  result = []
  header.each do |key, values|
    next unless values[:name]
    result << format_user_agent_header(key, values)
  end
  result.join(' ')
end
default_configuration() click to toggle source

Returns the default configuration @private

# File lib/contentful/client.rb, line 131
def default_configuration
  DEFAULT_CONFIGURATION.dup
end
do_build_resource(response) click to toggle source

Runs Resource Builder @private

# File lib/contentful/client.rb, line 382
def do_build_resource(response)
  logger.debug(response: response) if logger
  configuration[:resource_builder].new(
    response.object,
    configuration.merge(endpoint: response.request.endpoint),
    (response.request.query || {}).fetch(:locale, nil) == '*',
    0,
    [],
    response.request.query || {}
  ).run
end
entries(query = {}) click to toggle source

Gets a collection of entries

@param [Hash] query

@return [Contentful::Array<Contentful::Entry>]

# File lib/contentful/client.rb, line 184
def entries(query = {})
  normalize_select!(query)
  Request.new(self, environment_url('/entries'), query).get
end
entry(id, query = {}) click to toggle source

Gets a specific entry

@param [String] id @param [Hash] query

@return [Contentful::Entry]

# File lib/contentful/client.rb, line 169
def entry(id, query = {})
  normalize_select!(query)
  query['sys.id'] = id
  entries = Request.new(self, environment_url('/entries'), query).get

  return entries if configuration[:raw_mode]

  entries.first
end
environment_url(path) click to toggle source

Returns the url aware of the currently selected environment @private

# File lib/contentful/client.rb, line 226
def environment_url(path)
  "/environments/#{configuration[:environment]}#{path}"
end
fail_response(response) click to toggle source

@private

# File lib/contentful/client.rb, line 354
def fail_response(response)
  fail response.object if configuration[:raise_errors]
  response.object
end
format_user_agent_header(key, values) click to toggle source

Returns the formatted part of the X-Contentful-User-Agent header @private

# File lib/contentful/client.rb, line 232
def format_user_agent_header(key, values)
  header = "#{key} #{values[:name]}"
  header = "#{header}/#{values[:version]}" if values[:version]
  "#{header};"
end
get(request, build_resource = true) click to toggle source

Get a Contentful::Request object Set second parameter to false to deactivate Resource building and return Response objects instead

@private

# File lib/contentful/client.rb, line 316
def get(request, build_resource = true)
  retries_left = configuration[:max_rate_limit_retries]
  result = nil
  begin
    response = run_request(request)

    return response if !build_resource || configuration[:raw_mode]

    return fail_response(response) if response.status != :ok

    result = do_build_resource(response)
  rescue UnparsableResource => error
    raise error if configuration[:raise_errors]
    return error
  rescue Contentful::RateLimitExceeded => rate_limit_error
    reset_time = rate_limit_error.reset_time.to_i
    if should_retry(retries_left, reset_time, configuration[:max_rate_limit_wait])
      retries_left -= 1
      logger.info(retry_message(retries_left, reset_time)) if logger
      sleep(reset_time * Random.new.rand(1.0..1.2))
      retry
    end

    raise
  end

  result
end
integration_info() click to toggle source

Returns the X-Contentful-User-Agent integration data @private

# File lib/contentful/client.rb, line 252
def integration_info
  { name: configuration[:integration_name], version: configuration[:integration_version] }
end
locales(query = {}) click to toggle source

Gets a collection of locales for the current environment

@param [Hash] query

@return [Contentful::Array<Contentful::Locale>]

# File lib/contentful/client.rb, line 214
def locales(query = {})
  Request.new(self, environment_url('/locales'), query).get
end
os_info() click to toggle source

Returns the X-Contentful-User-Agent os data @private

# File lib/contentful/client.rb, line 264
def os_info
  os_name = case ::RbConfig::CONFIG['host_os']
            when /(cygwin|mingw|mswin|windows)/i then 'Windows'
            when /(darwin|macruby|mac os)/i      then 'macOS'
            when /(linux|bsd|aix|solarix)/i      then 'Linux'
            end
  { name: os_name, version: Gem::Platform.local.version }
end
platform_info() click to toggle source

Returns the X-Contentful-User-Agent platform data @private

# File lib/contentful/client.rb, line 258
def platform_info
  { name: 'ruby', version: RUBY_VERSION }
end
proxy_params() click to toggle source

@private

# File lib/contentful/client.rb, line 111
def proxy_params
  {
    host: configuration[:proxy_host],
    port: configuration[:proxy_port],
    username: configuration[:proxy_username],
    password: configuration[:proxy_password]
  }
end
register_dynamic_entry(key, klass) click to toggle source

Use this method to manually register a dynamic entry See examples/dynamic_entries.rb @private

# File lib/contentful/client.rb, line 407
def register_dynamic_entry(key, klass)
  ContentTypeCache.cache_set(configuration[:space], key, klass)
end
request_headers() click to toggle source

Returns the headers used for the HTTP requests @private

# File lib/contentful/client.rb, line 294
def request_headers
  headers = { 'X-Contentful-User-Agent' => contentful_user_agent }
  headers['Authorization'] = "Bearer #{configuration[:access_token]}" if configuration[:authentication_mechanism] == :header
  headers['Content-Type'] = "application/vnd.contentful.delivery.v#{configuration[:api_version].to_i}+json" if configuration[:api_version]
  headers['Accept-Encoding'] = 'gzip' if configuration[:gzip_encoded]
  headers
end
request_query(query) click to toggle source

Patches a query hash with the client configurations for queries @private

# File lib/contentful/client.rb, line 304
def request_query(query)
  if configuration[:authentication_mechanism] == :query_string
    query['access_token'] = configuration[:access_token]
  end
  query
end
retry_message(retries_left, reset_time) click to toggle source

@private

# File lib/contentful/client.rb, line 346
def retry_message(retries_left, reset_time)
  message = 'Contentful API Rate Limit Hit! '
  message += "Retrying - Retries left: #{retries_left}"
  message += "- Time until reset (seconds): #{reset_time}"
  message
end
run_request(request) click to toggle source

Runs request and parses Response @private

# File lib/contentful/client.rb, line 366
def run_request(request)
  url = request.absolute? ? request.url : base_url + request.url
  logger.info(request: { url: url, query: request.query, header: request_headers }) if logger
  Response.new(
    self.class.get_http(
      url,
      request_query(request.query),
      request_headers,
      proxy_params,
      timeout_params
    ), request
  )
end
sdk_info() click to toggle source

Returns the X-Contentful-User-Agent sdk data @private

# File lib/contentful/client.rb, line 240
def sdk_info
  { name: 'contentful.rb', version: ::Contentful::VERSION }
end
setup_logger() click to toggle source

@private

# File lib/contentful/client.rb, line 105
def setup_logger
  @logger = configuration[:logger]
  logger.level = configuration[:log_level] if logger && configuration.key?(:log_level)
end
should_retry(retries_left, reset_time, max_wait) click to toggle source

@private

# File lib/contentful/client.rb, line 360
def should_retry(retries_left, reset_time, max_wait)
  retries_left > 0 && max_wait > reset_time
end
space(query = {}) click to toggle source

Gets the client’s space

@param [Hash] query

@return [Contentful::Space]

# File lib/contentful/client.rb, line 140
def space(query = {})
  Request.new(self, '', query).get
end
sync(options = { initial: true }) click to toggle source

Create a new synchronisation object

@param [Hash, String] options Options or Sync URL

@note You will need to call each_page or first_page on it

@return [Contentful::Sync]

# File lib/contentful/client.rb, line 418
def sync(options = { initial: true })
  Sync.new(self, options)
end
timeout_params() click to toggle source

@private

# File lib/contentful/client.rb, line 121
def timeout_params
  {
    connect: configuration[:timeout_connect],
    read: configuration[:timeout_read],
    write: configuration[:timeout_write]
  }.reject { |_, value| value.nil? }
end
update_dynamic_entry_cache!() click to toggle source

Use this method together with the client’s :dynamic_entries configuration. See README for details. @private

# File lib/contentful/client.rb, line 397
def update_dynamic_entry_cache!
  return if configuration[:raw_mode]
  content_types(limit: 1000).map do |ct|
    ContentTypeCache.cache_set(configuration[:space], ct.id, ct)
  end
end

Private Instance Methods

normalize_configuration!() click to toggle source
# File lib/contentful/client.rb, line 436
def normalize_configuration!
  %i[space access_token api_url default_locale].each { |s| configuration[s] = configuration[s].to_s }
  configuration[:authentication_mechanism] = configuration[:authentication_mechanism].to_sym
end
normalize_select!(query) click to toggle source

If the query contains the :select operator, we enforce :sys properties. The SDK requires sys.type to function properly, but as other of our SDKs require more parts of the :sys properties, we decided that every SDK should include the complete :sys block to provide consistency accross our SDKs.

# File lib/contentful/client.rb, line 428
def normalize_select!(query)
  return unless query.key?(:select)

  query[:select] = query[:select].split(',').map(&:strip) if query[:select].is_a? String
  query[:select] = query[:select].reject { |p| p.start_with?('sys.') }
  query[:select] << 'sys' unless query[:select].include?('sys')
end
validate_configuration!() click to toggle source
# File lib/contentful/client.rb, line 441
def validate_configuration!
  fail ArgumentError, 'You will need to initialize a client with a :space' if configuration[:space].empty?
  fail ArgumentError, 'You will need to initialize a client with an :access_token' if configuration[:access_token].empty?
  fail ArgumentError, 'The client configuration needs to contain an :api_url' if configuration[:api_url].empty?
  fail ArgumentError, 'The client configuration needs to contain a :default_locale' if configuration[:default_locale].empty?
  fail ArgumentError, 'The :api_version must be a positive number or nil' unless configuration[:api_version].to_i >= 0
  fail ArgumentError, 'The authentication mechanism must be :header or :query_string' unless %i[header query_string].include?(
    configuration[:authentication_mechanism]
  )
  fail ArgumentError, 'The :dynamic_entries mode must be :auto or :manual' unless %i[auto manual].include?(
    configuration[:dynamic_entries]
  )
  fail ArgumentError, 'Timeout parameters must be all omitted or all present' unless timeout_params.empty? || timeout_params.length == 3
end