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)


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

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.



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

def api_key
  @api_key
end

#application_idObject (readonly)

Returns the value of attribute application_id.



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

def application_id
  @application_id
end

#batch_timeoutObject (readonly)

Returns the value of attribute batch_timeout.



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

def batch_timeout
  @batch_timeout
end

#connect_timeoutObject (readonly)

Returns the value of attribute connect_timeout.



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

def connect_timeout
  @connect_timeout
end

#headersObject (readonly)

Returns the value of attribute headers.



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

def headers
  @headers
end

#hostsObject (readonly)

Returns the value of attribute hosts.



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

def hosts
  @hosts
end

#receive_timeoutObject (readonly)

Returns the value of attribute receive_timeout.



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

def receive_timeout
  @receive_timeout
end

#search_hostsObject (readonly)

Returns the value of attribute search_hosts.



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

def search_hosts
  @search_hosts
end

#search_timeoutObject (readonly)

Returns the value of attribute search_timeout.



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

def search_timeout
  @search_timeout
end

#send_timeoutObject (readonly)

Returns the value of attribute send_timeout.



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

def send_timeout
  @send_timeout
end

#sslObject (readonly)

Returns the value of attribute ssl.



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

def ssl
  @ssl
end

#ssl_versionObject (readonly)

Returns the value of attribute ssl_version.



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

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


227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/algolia/client.rb', line 227

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



303
304
305
# File 'lib/algolia/client.rb', line 303

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



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

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).



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

def copy_index(src_index, dst_index)
  request = {"operation" => "copy", "destination" => dst_index};
  Algolia.client.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).



155
156
157
158
159
# File 'lib/algolia/client.rb', line 155

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

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



363
364
365
# File 'lib/algolia/client.rb', line 363

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

#delete_index(name) ⇒ Object

Delete an index



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

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

#delete_index!(name) ⇒ Object

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



169
170
171
# File 'lib/algolia/client.rb', line 169

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

#delete_user_key(key) ⇒ Object

Delete an existing user key



298
299
300
# File 'lib/algolia/client.rb', line 298

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

#disable_rate_limit_forwardObject

Disable IP rate limit enabled with enableRateLimitForward() function



73
74
75
76
77
# File 'lib/algolia/client.rb', line 73

def disable_rate_limit_forward
  headers[Protocol::HEADER_API_KEY] = Algolia.client.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



64
65
66
67
68
# File 'lib/algolia/client.rb', line 64

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



351
352
353
# File 'lib/algolia/client.rb', line 351

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.



179
180
181
182
183
184
185
186
187
188
# File 'lib/algolia/client.rb', line 179

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



196
197
198
# File 'lib/algolia/client.rb', line 196

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

#init_index(name) ⇒ Object

Initialize a new index



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

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"}]}


115
116
117
# File 'lib/algolia/client.rb', line 115

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

#list_user_keysObject

List all existing user keys with their associated ACLs



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

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).



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

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).



134
135
136
137
138
# File 'lib/algolia/client.rb', line 134

def move_index!(src_index, dst_index)
  res = Algolia.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)



98
99
100
101
102
103
104
105
106
107
# File 'lib/algolia/client.rb', line 98

def multiple_queries(queries, index_name_key = :index_name, strategy = "none")
  requests = {
    :requests => queries.map do |query|
      indexName = query.delete(index_name_key) || query.delete(index_name_key.to_s)
      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



355
356
357
# File 'lib/algolia/client.rb', line 355

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

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



359
360
361
# File 'lib/algolia/client.rb', line 359

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.



319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/algolia/client.rb', line 319

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

  (type == :write ? @hosts : @search_hosts).size.times do |i|
    connect_timeout += 2 if i == 2
    send_timeout += 10 if i == 2
    receive_timeout += 10 if i == 2

    host = thread_local_hosts(type != :write, connect_timeout, send_timeout, receive_timeout)[i]
    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
  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



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

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


275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/algolia/client.rb', line 275

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



82
83
84
85
86
87
88
89
# File 'lib/algolia/client.rb', line 82

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