Class: Algolia::Client

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

Overview

A class which encapsulates the HTTPS communication with the Algolia API server. Uses the HTTPClient library for low-level HTTP communication.

Constant Summary collapse

DEFAULT_CONNECT_TIMEOUT =
2
DEFAULT_RECEIVE_TIMEOUT =
30
DEFAULT_SEND_TIMEOUT =
30
DEFAULT_BATCH_TIMEOUT =
120
DEFAULT_SEARCH_TIMEOUT =
5

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data = {}) ⇒ Client

Returns a new instance of Client.

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/algolia/client.rb', line 22

def initialize(data = {})
  raise ArgumentError.new("No APPLICATION_ID provided, please set :application_id") if data[:application_id].nil?

  @ssl             = data[:ssl].nil? ? true : data[:ssl]
  @ssl_version     = data[:ssl_version].nil? ? nil : data[:ssl_version]
  @application_id  = data[:application_id]
  @api_key         = data[:api_key]
  @hosts           = data[:hosts] || (["#{@application_id}.algolia.net"] + 1.upto(3).map { |i| "#{@application_id}-#{i}.algolianet.com" }.shuffle)
  @search_hosts    = data[:search_hosts] || data[:hosts] || (["#{@application_id}-dsn.algolia.net"] + 1.upto(3).map { |i| "#{@application_id}-#{i}.algolianet.com" }.shuffle)
  @connect_timeout = data[:connect_timeout] || DEFAULT_CONNECT_TIMEOUT
  @send_timeout    = data[:send_timeout] || DEFAULT_SEND_TIMEOUT
  @batch_timeout   = data[:batch_timeout] || DEFAULT_BATCH_TIMEOUT
  @receive_timeout = data[:receive_timeout] || DEFAULT_RECEIVE_TIMEOUT
  @search_timeout  = data[:search_timeout] || DEFAULT_SEARCH_TIMEOUT
  @headers = {
    Protocol::HEADER_API_KEY => api_key,
    Protocol::HEADER_APP_ID  => application_id,
    'Content-Type'           => 'application/json; charset=utf-8',
    'User-Agent'             => "Algolia for Ruby #{::Algolia::VERSION}"
  }
end

Instance Attribute Details

#api_keyObject (readonly)

Returns the value of attribute api_key.



14
15
16
# File 'lib/algolia/client.rb', line 14

def api_key
  @api_key
end

#application_idObject (readonly)

Returns the value of attribute application_id.



14
15
16
# File 'lib/algolia/client.rb', line 14

def application_id
  @application_id
end

#batch_timeoutObject (readonly)

Returns the value of attribute batch_timeout.



14
15
16
# File 'lib/algolia/client.rb', line 14

def batch_timeout
  @batch_timeout
end

#connect_timeoutObject (readonly)

Returns the value of attribute connect_timeout.



14
15
16
# File 'lib/algolia/client.rb', line 14

def connect_timeout
  @connect_timeout
end

#headersObject (readonly)

Returns the value of attribute headers.



14
15
16
# File 'lib/algolia/client.rb', line 14

def headers
  @headers
end

#hostsObject (readonly)

Returns the value of attribute hosts.



14
15
16
# File 'lib/algolia/client.rb', line 14

def hosts
  @hosts
end

#receive_timeoutObject (readonly)

Returns the value of attribute receive_timeout.



14
15
16
# File 'lib/algolia/client.rb', line 14

def receive_timeout
  @receive_timeout
end

#search_hostsObject (readonly)

Returns the value of attribute search_hosts.



14
15
16
# File 'lib/algolia/client.rb', line 14

def search_hosts
  @search_hosts
end

#search_timeoutObject (readonly)

Returns the value of attribute search_timeout.



14
15
16
# File 'lib/algolia/client.rb', line 14

def search_timeout
  @search_timeout
end

#send_timeoutObject (readonly)

Returns the value of attribute send_timeout.



14
15
16
# File 'lib/algolia/client.rb', line 14

def send_timeout
  @send_timeout
end

#sslObject (readonly)

Returns the value of attribute ssl.



14
15
16
# File 'lib/algolia/client.rb', line 14

def ssl
  @ssl
end

#ssl_versionObject (readonly)

Returns the value of attribute ssl_version.



14
15
16
# File 'lib/algolia/client.rb', line 14

def ssl_version
  @ssl_version
end

Instance Method Details

#add_user_key(obj, validity = 0, maxQueriesPerIPPerHour = 0, maxHitsPerQuery = 0, indexes = nil) ⇒ Object

Create a new user key

@param obj can be two different parameters:
      The list of parameters for this key. Defined by a NSDictionary that
      can contains the following values:
        - acl: array of string
        - indices: array of string
        - validity: int
        - referers: array of string
        - description: string
        - maxHitsPerQuery: integer
        - queryParameters: string
        - maxQueriesPerIPPerHour: integer
      Or the list of ACL for this key. Defined by an array of NSString that
      can contains the following values:
        - search: allow to search (https and http)
        - addObject: allows to add/update an object in the index (https only)
        - deleteObject : allows to delete an existing object (https only)
        - deleteIndex : allows to delete index content (https only)
        - settings : allows to get index settings (https only)
        - editSettings : allows to change index settings (https only)
@param validity the number of seconds after which the key will be automatically removed (0 means no time limit for this key)
@param maxQueriesPerIPPerHour the maximum number of API calls allowed from an IP address per hour (0 means unlimited)
@param maxHitsPerQuery  the maximum number of hits this API key can retrieve in one call (0 means unlimited)
@param indexes the optional list of targeted indexes


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/algolia/client.rb', line 235

def add_user_key(obj, validity = 0, maxQueriesPerIPPerHour = 0, maxHitsPerQuery = 0, indexes = nil)
  if obj.instance_of? Array
    params = {
      :acl => obj
    }
  else
    params = obj
  end
  if validity != 0
    params["validity"] = validity.to_i
  end
  if maxQueriesPerIPPerHour != 0
    params["maxQueriesPerIPPerHour"] = maxQueriesPerIPPerHour.to_i
  end
  if maxHitsPerQuery != 0
    params["maxHitsPerQuery"] = maxHitsPerQuery.to_i
  end
  params[:indexes] = indexes if indexes
  post(Protocol.keys_uri, params.to_json)
end

#batch(requests) ⇒ Object

Send a batch request targeting multiple indices



311
312
313
# File 'lib/algolia/client.rb', line 311

def batch(requests)
  post(Protocol.batch_uri, {"requests" => requests}.to_json, :batch)
end

#batch!(requests) ⇒ Object

Send a batch request targeting multiple indices and wait the end of the indexing



316
317
318
319
320
321
# File 'lib/algolia/client.rb', line 316

def batch!(requests)
  res = batch(requests)
  res['taskID'].each do |index, taskID|
    init_index(index).wait_task(taskID)
  end
end

#copy_index(src_index, dst_index) ⇒ Object

Copy an existing index.

Parameters:

  • src_index

    the name of index to copy.

  • dst_index

    the new index name that will contains a copy of srcIndexName (destination will be overriten if it already exist).



153
154
155
156
# File 'lib/algolia/client.rb', line 153

def copy_index(src_index, dst_index)
  request = {"operation" => "copy", "destination" => dst_index};
  post(Protocol.index_operation_uri(src_index), request.to_json)
end

#copy_index!(src_index, dst_index) ⇒ Object

Copy an existing index and wait until the copy has been processed.

Parameters:

  • src_index

    the name of index to copy.

  • dst_index

    the new index name that will contains a copy of srcIndexName (destination will be overriten if it already exist).



163
164
165
166
167
# File 'lib/algolia/client.rb', line 163

def copy_index!(src_index, dst_index)
  res = copy_index(src_index, dst_index)
  init_index(dst_index).wait_task(res['taskID'])
  res
end

#delete(uri, type = :write) ⇒ Object



378
379
380
# File 'lib/algolia/client.rb', line 378

def delete(uri, type = :write)
  request(uri, :DELETE, nil, type)
end

#delete_index(name) ⇒ Object

Delete an index



171
172
173
# File 'lib/algolia/client.rb', line 171

def delete_index(name)
  init_index(name).delete
end

#delete_index!(name) ⇒ Object

Delete an index and wait until the deletion has been processed.



177
178
179
# File 'lib/algolia/client.rb', line 177

def delete_index!(name)
  init_index(name).delete!
end

#delete_user_key(key) ⇒ Object

Delete an existing user key



306
307
308
# File 'lib/algolia/client.rb', line 306

def delete_user_key(key)
  delete(Protocol.key_uri(key))
end

#destroyObject



44
45
46
47
# File 'lib/algolia/client.rb', line 44

def destroy
  Thread.current["algolia_search_hosts_#{application_id}"] = nil
  Thread.current["algolia_hosts_#{application_id}"] = nil
end

#disable_rate_limit_forwardObject

Disable IP rate limit enabled with enableRateLimitForward() function



79
80
81
82
83
# File 'lib/algolia/client.rb', line 79

def disable_rate_limit_forward
  headers[Protocol::HEADER_API_KEY] = api_key
  headers.delete(Protocol::HEADER_FORWARDED_IP)
  headers.delete(Protocol::HEADER_FORWARDED_API_KEY)
end

#enable_rate_limit_forward(admin_api_key, end_user_ip, rate_limit_api_key) ⇒ Object

Allow to use IP rate limit when you have a proxy between end-user and Algolia. This option will set the X-Forwarded-For HTTP header with the client IP and the X-Forwarded-API-Key with the API Key having rate limits.

Parameters:

  • admin_api_key

    the admin API Key you can find in your dashboard

  • end_user_ip

    the end user IP (you can use both IPV4 or IPV6 syntax)

  • rate_limit_api_key

    the API key on which you have a rate limit



70
71
72
73
74
# File 'lib/algolia/client.rb', line 70

def enable_rate_limit_forward(admin_api_key, end_user_ip, rate_limit_api_key)
  headers[Protocol::HEADER_API_KEY] = admin_api_key
  headers[Protocol::HEADER_FORWARDED_IP] = end_user_ip
  headers[Protocol::HEADER_FORWARDED_API_KEY] = rate_limit_api_key
end

#get(uri, type = :write) ⇒ Object



366
367
368
# File 'lib/algolia/client.rb', line 366

def get(uri, type = :write)
  request(uri, :GET, nil, type)
end

#get_logs(offset = 0, length = 10, type = "all") ⇒ Object

Return last logs entries.

Parameters:

  • offset (defaults to: 0)

    Specify the first entry to retrieve (0-based, 0 is the most recent log entry).

  • length (defaults to: 10)

    Specify the maximum number of entries to retrieve starting at offset. Maximum allowed value: 1000.



187
188
189
190
191
192
193
194
195
196
# File 'lib/algolia/client.rb', line 187

def get_logs(offset = 0, length = 10, type = "all")
  if (type.is_a?(true.class))
    if (type)
      type = "error"
    else
      type = "all"
    end
  end
  get(Protocol.logs(offset, length, type))
end

#get_user_key(key) ⇒ Object

Get ACL of a user key



204
205
206
# File 'lib/algolia/client.rb', line 204

def get_user_key(key)
  get(Protocol.key_uri(key), :read)
end

#init_index(name) ⇒ Object

Initialize a new index



52
53
54
# File 'lib/algolia/client.rb', line 52

def init_index(name)
  Index.new(name, self)
end

#list_indexesObject

List all existing indexes return an Answer object with answer in the form

{"items": [{ "name": "contacts", "createdAt": "2013-01-18T15:33:13.556Z"},
           {"name": "notes", "createdAt": "2013-01-18T15:33:13.556Z"}]}


123
124
125
# File 'lib/algolia/client.rb', line 123

def list_indexes
  get(Protocol.indexes_uri, :read)
end

#list_user_keysObject

List all existing user keys with their associated ACLs



199
200
201
# File 'lib/algolia/client.rb', line 199

def list_user_keys
  get(Protocol.keys_uri, :read)
end

#move_index(src_index, dst_index) ⇒ Object

Move an existing index.

Parameters:

  • src_index

    the name of index to copy.

  • dst_index

    the new index name that will contains a copy of srcIndexName (destination will be overriten if it already exist).



132
133
134
135
# File 'lib/algolia/client.rb', line 132

def move_index(src_index, dst_index)
  request = {"operation" => "move", "destination" => dst_index};
  post(Protocol.index_operation_uri(src_index), request.to_json)
end

#move_index!(src_index, dst_index) ⇒ Object

Move an existing index and wait until the move has been processed

Parameters:

  • src_index

    the name of index to copy.

  • dst_index

    the new index name that will contains a copy of srcIndexName (destination will be overriten if it already exist).



142
143
144
145
146
# File 'lib/algolia/client.rb', line 142

def move_index!(src_index, dst_index)
  res = move_index(src_index, dst_index)
  init_index(dst_index).wait_task(res['taskID'])
  res
end

#multiple_queries(queries, index_name_key = :index_name, strategy = "none") ⇒ Object

This method allows to query multiple indexes with one API call

Parameters:

  • queries

    the array of hash representing the query and associated index name

  • index_name_key (defaults to: :index_name)

    the name of the key used to fetch the index_name (:index_name by default)

  • strategy (defaults to: "none")

    define the strategy applied on the sequential searches (none by default)



104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/algolia/client.rb', line 104

def multiple_queries(queries, index_name_key = :index_name, strategy = "none")
  requests = {
    :requests => queries.map do |query|
      query = query.dup
      indexName = query.delete(index_name_key) || query.delete(index_name_key.to_s)
      raise ArgumentError.new("Missing '#{index_name_key}' option") if indexName.nil?
      encoded_params = Hash[query.map { |k,v| [k.to_s, v.is_a?(Array) ? v.to_json : v] }]
      { :indexName => indexName, :params => Protocol.to_query(encoded_params) }
    end
  }
  post(Protocol.multiple_queries_uri(strategy), requests.to_json, :search)
end

#post(uri, body = {}, type = :write) ⇒ Object



370
371
372
# File 'lib/algolia/client.rb', line 370

def post(uri, body = {}, type = :write)
  request(uri, :POST, body, type)
end

#put(uri, body = {}, type = :write) ⇒ Object



374
375
376
# File 'lib/algolia/client.rb', line 374

def put(uri, body = {}, type = :write)
  request(uri, :PUT, body, type)
end

#request(uri, method, data = nil, type = :write) ⇒ Object

Perform an HTTP request for the given uri and method with common basic response handling. Will raise a AlgoliaProtocolError if the response has an error status code, and will return the parsed JSON body on success, if there is one.



327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/algolia/client.rb', line 327

def request(uri, method, data = nil, type = :write)
  exceptions = []

  connect_timeout = @connect_timeout
  send_timeout = if type == :search
    @search_timeout
  elsif type == :batch
    type = :write
    @batch_timeout
  else
    @send_timeout
  end
  receive_timeout = type == :search ? @search_timeout : @receive_timeout

  thread_local_hosts(type != :write).each_with_index do |host, i|
    connect_timeout += 2 if i == 2
    send_timeout += 10 if i == 2
    receive_timeout += 10 if i == 2

    thread_index_key = type != :write ? "algolia_search_host_index_#{application_id}" : "algolia_host_index_#{application_id}"
    Thread.current[thread_index_key] = host[:index]
    host[:last_call] = Time.now.to_i

    host[:session].connect_timeout = connect_timeout
    host[:session].send_timeout = send_timeout
    host[:session].receive_timeout = receive_timeout
    begin
      return perform_request(host[:session], host[:base_url] + uri, method, data)
    rescue AlgoliaProtocolError => e
      raise if e.code / 100 == 4
      exceptions << e
    rescue => e
      exceptions << e
    end
    host[:session].reset_all
  end
  raise AlgoliaProtocolError.new(0, "Cannot reach any host: #{exceptions.map { |e| e.to_s }.join(', ')}")
end

#set_extra_header(key, value) ⇒ Object

Allow to set custom headers



59
60
61
# File 'lib/algolia/client.rb', line 59

def set_extra_header(key, value)
  headers[key] = value
end

#update_user_key(key, obj, validity = 0, maxQueriesPerIPPerHour = 0, maxHitsPerQuery = 0, indexes = nil) ⇒ Object

Update a user key

@param obj can be two different parameters:
      The list of parameters for this key. Defined by a NSDictionary that
      can contains the following values:
        - acl: array of string
        - indices: array of string
        - validity: int
        - referers: array of string
        - description: string
        - maxHitsPerQuery: integer
        - queryParameters: string
        - maxQueriesPerIPPerHour: integer
      Or the list of ACL for this key. Defined by an array of NSString that
      can contains the following values:
        - search: allow to search (https and http)
        - addObject: allows to add/update an object in the index (https only)
        - deleteObject : allows to delete an existing object (https only)
        - deleteIndex : allows to delete index content (https only)
        - settings : allows to get index settings (https only)
        - editSettings : allows to change index settings (https only)
@param validity the number of seconds after which the key will be automatically removed (0 means no time limit for this key)
@param maxQueriesPerIPPerHour the maximum number of API calls allowed from an IP address per hour (0 means unlimited)
@param maxHitsPerQuery  the maximum number of hits this API key can retrieve in one call (0 means unlimited)
@param indexes the optional list of targeted indexes


283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/algolia/client.rb', line 283

def update_user_key(key, obj, validity = 0, maxQueriesPerIPPerHour = 0, maxHitsPerQuery = 0, indexes = nil)
  if obj.instance_of? Array
    params = {
      :acl => obj
    }
  else
    params = obj
  end
  if validity != 0
    params["validity"] = validity.to_i
  end
  if maxQueriesPerIPPerHour != 0
    params["maxQueriesPerIPPerHour"] = maxQueriesPerIPPerHour.to_i
  end
  if maxHitsPerQuery != 0
    params["maxHitsPerQuery"] = maxHitsPerQuery.to_i
  end
  params[:indexes] = indexes if indexes
  put(Protocol.key_uri(key), params.to_json)
end

#with_rate_limits(end_user_ip, rate_limit_api_key, &block) ⇒ Object

Convenience method thats wraps enable_rate_limit_forward/disable_rate_limit_forward



88
89
90
91
92
93
94
95
# File 'lib/algolia/client.rb', line 88

def with_rate_limits(end_user_ip, rate_limit_api_key, &block)
  enable_rate_limit_forward(api_key, end_user_ip, rate_limit_api_key)
  begin
    yield
  ensure
    disable_rate_limit_forward
  end
end