Class: Contentful::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/contentful/client.rb

Overview

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

Constant Summary collapse

DEFAULT_CONFIGURATION =

Default configuration for Contentful::Client

{
  secure: true,
  raise_errors: true,
  raise_for_empty_fields: true,
  dynamic_entries: :manual,
  api_url: 'cdn.contentful.com',
  api_version: 1,
  environment: 'master',
  authentication_mechanism: :header,
  resource_builder: ResourceBuilder,
  resource_mapping: {},
  entry_mapping: {},
  default_locale: 'en-US',
  raw_mode: false,
  gzip_encoded: true,
  logger: false,
  proxy_host: nil,
  proxy_username: nil,
  proxy_password: nil,
  proxy_port: nil,
  timeout_connect: nil,
  timeout_read: nil,
  timeout_write: nil,
  max_rate_limit_retries: 1,
  max_rate_limit_wait: 60,
  max_include_resolution_depth: 20,
  use_camel_case: false,
  application_name: nil,
  application_version: nil,
  integration_name: nil,
  integration_version: nil,
  http_instrumenter: nil
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(given_configuration = {}) ⇒ Client

Returns a new instance of Client.

Parameters:

  • given_configuration (Hash) (defaults to: {})

Options Hash (given_configuration):

  • :space (String)

    Required

  • :access_token (String)

    Required

  • :api_url (String)

    Modifying this to ‘preview.contentful.com’ gives you access to our Preview API

  • :api_version (String)
  • :default_locale (String)
  • :proxy_host (String)
  • :proxy_username (String)
  • :proxy_password (String)
  • :proxy_port (Number)
  • :timeout_read (Number)
  • :timeout_write (Number)
  • :timeout_connect (Number)
  • :max_rate_limit_retries (Number)
  • :max_rate_limit_wait (Number)
  • :max_include_resolution_depth (Number)
  • :use_camel_case (Boolean)
  • :gzip_encoded (Boolean)
  • :raw_mode (Boolean)
  • :logger (false, ::Logger)
  • :log_level (::Logger::DEBUG, ::Logger::INFO, ::Logger::WARN, ::Logger::ERROR)
  • :raise_errors (Boolean)
  • :raise_for_empty_fields (Boolean)
  • :dynamic_entries (::Array<String>)
  • :resource_mapping (::Hash<String, Contentful::Resource>)
  • :entry_mapping (::Hash<String, Contentful::Resource>)
  • :application_name (String)
  • :application_version (String)
  • :integration_name (String)
  • :integration_version (String)
  • :http_instrumenter (HTTP::Features::Instrumentation::Instrumenter, nil)

    An HTTP instrumenter object that implements the instrumentation interface. When provided, it will be used to instrument all HTTP requests made by the client. This is useful for monitoring, logging, or tracking HTTP requests.

See Also:

  • https://github.com/contentful/contentful.rb#client-configuration-options


101
102
103
104
105
106
107
108
# File 'lib/contentful/client.rb', line 101

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

Instance Attribute Details

#configurationObject (readonly)

Returns the value of attribute configuration.



51
52
53
# File 'lib/contentful/client.rb', line 51

def configuration
  @configuration
end

#loggerObject (readonly)

Returns the value of attribute logger.



51
52
53
# File 'lib/contentful/client.rb', line 51

def logger
  @logger
end

#proxyObject (readonly)

Returns the value of attribute proxy.



51
52
53
# File 'lib/contentful/client.rb', line 51

def proxy
  @proxy
end

Class Method Details

.get_http(url, query, headers = {}, proxy = {}, timeout = {}, instrumenter) ⇒ Object

Wraps the actual HTTP request via proxy



55
56
57
58
59
60
61
62
63
64
# File 'lib/contentful/client.rb', line 55

def self.get_http(url, query, headers = {}, proxy = {}, timeout = {}, instrumenter)
  http = HTTP[headers]
  http = http.timeout(timeout) if timeout.any?
  http = http.use(instrumentation: { instrumenter: instrumenter }) if instrumenter
  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

Instance Method Details

#app_infoObject

Returns the X-Contentful-User-Agent app data



290
291
292
# File 'lib/contentful/client.rb', line 290

def app_info
  { name: configuration[:application_name], version: configuration[:application_version] }
end

#asset(id, query = {}) ⇒ Contentful::Asset

Gets a specific asset

Parameters:

  • id (String)
  • query (Hash) (defaults to: {})

Returns:



201
202
203
# File 'lib/contentful/client.rb', line 201

def asset(id, query = {})
  Request.new(self, environment_url('/assets'), query, id).get
end

#assets(query = {}) ⇒ Contentful::Array<Contentful::Asset>

Gets a collection of assets

Parameters:

  • query (Hash) (defaults to: {})

Returns:



210
211
212
213
# File 'lib/contentful/client.rb', line 210

def assets(query = {})
  normalize_select!(query)
  Request.new(self, environment_url('/assets'), query).get
end

#base_urlObject

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



264
265
266
# File 'lib/contentful/client.rb', line 264

def base_url
  "http#{configuration[:secure] ? 's' : ''}://#{configuration[:api_url]}/spaces/#{configuration[:space]}"
end

#content_type(id, query = {}) ⇒ Contentful::ContentType

Gets a specific content type

Parameters:

  • id (String)
  • query (Hash) (defaults to: {})

Returns:



156
157
158
# File 'lib/contentful/client.rb', line 156

def content_type(id, query = {})
  Request.new(self, environment_url('/content_types'), query, id).get
end

#content_types(query = {}) ⇒ Contentful::Array<Contentful::ContentType>

Gets a collection of content types

Parameters:

  • query (Hash) (defaults to: {})

Returns:



165
166
167
# File 'lib/contentful/client.rb', line 165

def content_types(query = {})
  Request.new(self, environment_url('/content_types'), query).get
end

#contentful_user_agentObject

Returns the X-Contentful-User-Agent



319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/contentful/client.rb', line 319

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_configurationObject

Returns the default configuration



137
138
139
# File 'lib/contentful/client.rb', line 137

def default_configuration
  DEFAULT_CONFIGURATION.dup
end

#do_build_resource(response) ⇒ Object

Runs Resource Builder



427
428
429
430
431
432
433
434
435
436
437
# File 'lib/contentful/client.rb', line 427

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 = {}) ⇒ Contentful::Array<Contentful::Entry>

Gets a collection of entries

Parameters:

  • query (Hash) (defaults to: {})

Returns:



190
191
192
193
# File 'lib/contentful/client.rb', line 190

def entries(query = {})
  normalize_select!(query)
  Request.new(self, environment_url('/entries'), query).get
end

#entry(id, query = {}) ⇒ Contentful::Entry

Gets a specific entry

Parameters:

  • id (String)
  • query (Hash) (defaults to: {})

Returns:



175
176
177
178
179
180
181
182
183
# File 'lib/contentful/client.rb', line 175

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) ⇒ Object

Returns the url aware of the currently selected environment



270
271
272
# File 'lib/contentful/client.rb', line 270

def environment_url(path)
  "/environments/#{configuration[:environment]}#{path}"
end

#fail_response(response) ⇒ Object



398
399
400
401
# File 'lib/contentful/client.rb', line 398

def fail_response(response)
  fail response.object if configuration[:raise_errors]
  response.object
end

#format_user_agent_header(key, values) ⇒ Object

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



276
277
278
279
280
# File 'lib/contentful/client.rb', line 276

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) ⇒ Object

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



360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# File 'lib/contentful/client.rb', line 360

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_infoObject

Returns the X-Contentful-User-Agent integration data



296
297
298
# File 'lib/contentful/client.rb', line 296

def integration_info
  { name: configuration[:integration_name], version: configuration[:integration_version] }
end

#locales(query = {}) ⇒ Contentful::Array<Contentful::Locale>

Gets a collection of locales for the current environment

Parameters:

  • query (Hash) (defaults to: {})

Returns:



220
221
222
# File 'lib/contentful/client.rb', line 220

def locales(query = {})
  Request.new(self, environment_url('/locales'), query).get
end

#os_infoObject

Returns the X-Contentful-User-Agent os data



308
309
310
311
312
313
314
315
# File 'lib/contentful/client.rb', line 308

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_infoObject

Returns the X-Contentful-User-Agent platform data



302
303
304
# File 'lib/contentful/client.rb', line 302

def platform_info
  { name: 'ruby', version: RUBY_VERSION }
end

#proxy_paramsObject



117
118
119
120
121
122
123
124
# File 'lib/contentful/client.rb', line 117

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) ⇒ Object

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



452
453
454
# File 'lib/contentful/client.rb', line 452

def register_dynamic_entry(key, klass)
  ContentTypeCache.cache_set(configuration[:space], key, klass)
end

#request_headersObject

Returns the headers used for the HTTP requests



338
339
340
341
342
343
344
# File 'lib/contentful/client.rb', line 338

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) ⇒ Object

Patches a query hash with the client configurations for queries



348
349
350
351
352
353
# File 'lib/contentful/client.rb', line 348

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) ⇒ Object



390
391
392
393
394
395
# File 'lib/contentful/client.rb', line 390

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) ⇒ Object

Runs request and parses Response



410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/contentful/client.rb', line 410

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,
      configuration[:http_instrumenter]
    ), request
  )
end

#sdk_infoObject

Returns the X-Contentful-User-Agent sdk data



284
285
286
# File 'lib/contentful/client.rb', line 284

def sdk_info
  { name: 'contentful.rb', version: ::Contentful::VERSION }
end

#setup_loggerObject



111
112
113
114
# File 'lib/contentful/client.rb', line 111

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) ⇒ Object



404
405
406
# File 'lib/contentful/client.rb', line 404

def should_retry(retries_left, reset_time, max_wait)
  retries_left > 0 && max_wait > reset_time
end

#space(query = {}) ⇒ Contentful::Space

Gets the client’s space

Parameters:

  • query (Hash) (defaults to: {})

Returns:



146
147
148
# File 'lib/contentful/client.rb', line 146

def space(query = {})
  Request.new(self, '', query).get
end

#sync(options = { initial: true }) ⇒ Contentful::Sync

Note:

You will need to call #each_page or #first_page on it

Create a new synchronisation object

Parameters:

  • options (Hash, String) (defaults to: { initial: true })

    Options or Sync URL

Returns:



463
464
465
# File 'lib/contentful/client.rb', line 463

def sync(options = { initial: true })
  Sync.new(self, options)
end

#taxonomy_concept(id, query = {}) ⇒ Contentful::TaxonomyConcept

Gets a specific taxonomy concept

Parameters:

  • id (String)
  • query (Hash) (defaults to: {})

Returns:



230
231
232
# File 'lib/contentful/client.rb', line 230

def taxonomy_concept(id, query = {})
  Request.new(self, environment_url('/taxonomy/concepts'), query, id).get
end

#taxonomy_concept_scheme(id, query = {}) ⇒ Contentful::TaxonomyConceptScheme

Gets a specific taxonomy concept scheme

Parameters:

  • id (String)
  • query (Hash) (defaults to: {})

Returns:



249
250
251
# File 'lib/contentful/client.rb', line 249

def taxonomy_concept_scheme(id, query = {})
  Request.new(self, environment_url('/taxonomy/concept-schemes'), query, id).get
end

#taxonomy_concept_schemes(query = {}) ⇒ Contentful::Array<Contentful::TaxonomyConceptScheme>

Gets a collection of taxonomy concept schemes

Parameters:

  • query (Hash) (defaults to: {})

Returns:



258
259
260
# File 'lib/contentful/client.rb', line 258

def taxonomy_concept_schemes(query = {})
  Request.new(self, environment_url('/taxonomy/concept-schemes'), query).get
end

#taxonomy_concepts(query = {}) ⇒ Contentful::Array<Contentful::TaxonomyConcept>

Gets a collection of taxonomy concepts

Parameters:

  • query (Hash) (defaults to: {})

Returns:



239
240
241
# File 'lib/contentful/client.rb', line 239

def taxonomy_concepts(query = {})
  Request.new(self, environment_url('/taxonomy/concepts'), query).get
end

#timeout_paramsObject



127
128
129
130
131
132
133
# File 'lib/contentful/client.rb', line 127

def timeout_params
  {
    connect: configuration[:timeout_connect],
    read: configuration[:timeout_read],
    write: configuration[:timeout_write]
  }.reject { |_, value| value.nil? }
end

#update_dynamic_entry_cache!Object

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



442
443
444
445
446
447
# File 'lib/contentful/client.rb', line 442

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