elasticsearch-transport 6.8.1 → 6.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +86 -32
  3. data/elasticsearch-transport.gemspec +44 -64
  4. data/lib/elasticsearch-transport.rb +4 -0
  5. data/lib/elasticsearch/transport.rb +4 -0
  6. data/lib/elasticsearch/transport/client.rb +51 -11
  7. data/lib/elasticsearch/transport/redacted.rb +4 -0
  8. data/lib/elasticsearch/transport/transport/base.rb +17 -7
  9. data/lib/elasticsearch/transport/transport/connections/collection.rb +4 -0
  10. data/lib/elasticsearch/transport/transport/connections/connection.rb +4 -0
  11. data/lib/elasticsearch/transport/transport/connections/selector.rb +4 -0
  12. data/lib/elasticsearch/transport/transport/errors.rb +4 -0
  13. data/lib/elasticsearch/transport/transport/http/curb.rb +6 -2
  14. data/lib/elasticsearch/transport/transport/http/faraday.rb +6 -2
  15. data/lib/elasticsearch/transport/transport/http/manticore.rb +5 -1
  16. data/lib/elasticsearch/transport/transport/response.rb +4 -0
  17. data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +4 -0
  18. data/lib/elasticsearch/transport/transport/sniffer.rb +31 -3
  19. data/lib/elasticsearch/transport/version.rb +5 -1
  20. data/spec/elasticsearch/transport/base_spec.rb +184 -0
  21. data/spec/elasticsearch/transport/client_spec.rb +117 -21
  22. data/spec/elasticsearch/transport/sniffer_spec.rb +269 -0
  23. data/spec/spec_helper.rb +4 -0
  24. data/test/integration/transport_test.rb +4 -0
  25. data/test/profile/client_benchmark_test.rb +4 -0
  26. data/test/test_helper.rb +4 -0
  27. data/test/unit/connection_collection_test.rb +4 -0
  28. data/test/unit/connection_selector_test.rb +4 -0
  29. data/test/unit/connection_test.rb +4 -0
  30. data/test/unit/response_test.rb +5 -1
  31. data/test/unit/serializer_test.rb +4 -0
  32. data/test/unit/transport_base_test.rb +4 -0
  33. data/test/unit/transport_curb_test.rb +4 -0
  34. data/test/unit/transport_faraday_test.rb +4 -0
  35. data/test/unit/transport_manticore_test.rb +4 -0
  36. metadata +68 -64
  37. data/test/unit/sniffer_test.rb +0 -179
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf520599f6e46c395ff1fceef21ca8695054edcfef671b79c2da2899fb71addd
4
- data.tar.gz: 45e976dc56a422aa28c4e88e25c640da7d344e73626a6fa2060a644c0110cc4b
3
+ metadata.gz: c036b32f60221fef3a8c617ddc30a55c50c916b4f3c235fe34f91917060c9ae4
4
+ data.tar.gz: 18d4582f2c6479fe2af5bf10a6f6cc97d6083172274be5de85d82a47f62b1a04
5
5
  SHA512:
6
- metadata.gz: f0e09ba9f20e715741a8f0443d9c18517ce145dd428f345831a74f41cb6dd08355b2b653e9b945b2ed4101b5dc1635f062c0ff1d7e89e5996515de7a614e5765
7
- data.tar.gz: 264296357a6866a21a86f268c919fea1309e7283e0c1be6f7fd2dc407350dfeaf16115072c82d021d0da43916db8c1832cfc842f9c72040df3c23360f58d480c
6
+ metadata.gz: a06a56942b78b094e562ef1fa4d6adfd9433a823aeb3e21e06296574c39bcb5c228b52a009fe3a375a8682a1d0e9c9d370ff74a5a84dce4d2800170ede4e3d5c
7
+ data.tar.gz: 8646819dd552fae0bbba12d03e0a2ed1c996f2d0493a0ad65c4f07bd5e2ae763d8067aefc66c8d52963def632d1a552c7271744233ba12a5b43945d281800d1c
data/README.md CHANGED
@@ -28,12 +28,16 @@ Features overview:
28
28
  * Node reloading (based on cluster state) on errors or on demand
29
29
 
30
30
  For optimal performance, use a HTTP library which supports persistent ("keep-alive") connections,
31
- such as [Typhoeus](https://github.com/typhoeus/typhoeus).
32
- Just require the library (`require 'typhoeus'; require 'typhoeus/adapters/faraday'`) in your code,
33
- and it will be automatically used; currently these libraries will be automatically detected and used:
34
- [Patron](https://github.com/toland/patron),
35
- [HTTPClient](https://rubygems.org/gems/httpclient) and
36
- [Net::HTTP::Persistent](https://rubygems.org/gems/net-http-persistent).
31
+ such as [patron](https://github.com/toland/patron).
32
+ Just require the library (`require 'patron'`) in your code,
33
+ and it will be automatically used.
34
+
35
+ Currently these libraries will be automatically detected and used:
36
+ - [Patron](https://github.com/toland/patron)
37
+ - [HTTPClient](https://rubygems.org/gems/httpclient)
38
+ - [Net::HTTP::Persistent](https://rubygems.org/gems/net-http-persistent)
39
+
40
+ **Note on [Typhoeus](https://github.com/typhoeus/typhoeus)**: Typhoeus is compatible and will be automatically detected too. However, the latest release (v1.3.1 at the moment of writing this) is not compatible with Faraday 1.0. [It still uses the deprecated `Faraday::Error` namespace](https://github.com/typhoeus/typhoeus/blob/v1.3.1/lib/typhoeus/adapters/faraday.rb#L100). If you want to use it with this gem, we suggest getting `master` from GitHub, since this has been fixed for v1.4.0. We'll update this if/when v1.4.0 is released.a
37
41
 
38
42
  For detailed information, see example configurations [below](#transport-implementations).
39
43
 
@@ -69,6 +73,22 @@ Full documentation is available at <http://rubydoc.info/gems/elasticsearch-trans
69
73
 
70
74
  ## Configuration
71
75
 
76
+ * [Setting Hosts](#setting-hosts)
77
+ * [Default port](#default-port)
78
+ * [Connect using an Elastic Cloud ID](#connect-using-an-elastic-cloud-id)
79
+ * [Authentication](#authentication)
80
+ * [Logging](#logging)
81
+ * [Identifying running tasks with X-Opaque-Id](#identifying-running-tasks-with-x-opaque-id)
82
+ * [Setting Timeouts](#setting-timeouts)
83
+ * [Randomizing Hosts](#randomizing-hosts)
84
+ * [Retrying on Failures](#retrying-on-failures)
85
+ * [Reloading Hosts](#reloading-hosts)
86
+ * [Connection Selector](#connection-selector)
87
+ * [Transport Implementations](#transport-implementations)
88
+ * [Serializer implementations](#serializer-implementations)
89
+ * [Exception Handling](#exception-handling)
90
+ * [Development and Community](#development-and-community)
91
+
72
92
  The client supports many configurations options for setting up and managing connections,
73
93
  configuring logging, customizing the transport library, etc.
74
94
 
@@ -128,6 +148,26 @@ use the `transport_options` option:
128
148
  Elasticsearch::Client.new url: 'https://username:password@example.com:9200',
129
149
  transport_options: { ssl: { ca_file: '/path/to/cacert.pem' } }
130
150
 
151
+ You can also use [**API Key authentication**](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html):
152
+
153
+ ``` ruby
154
+ Elasticsearch::Client.new(
155
+ host: host,
156
+ transport_options: transport_options,
157
+ api_key: credentials
158
+ )
159
+ ```
160
+
161
+ Where credentials is either the base64 encoding of `id` and `api_key` joined by a colon or a hash with the `id` and `api_key`:
162
+
163
+ ``` ruby
164
+ Elasticsearch::Client.new(
165
+ host: host,
166
+ transport_options: transport_options,
167
+ api_key: {id: 'my_id', api_key: 'my_api_key'}
168
+ )
169
+ ```
170
+
131
171
  ### Logging
132
172
 
133
173
  To log requests and responses to standard output with the default logger (an instance of Ruby's {::Logger} class),
@@ -158,6 +198,29 @@ You can pass the client any conforming logger implementation:
158
198
 
159
199
  client = Elasticsearch::Client.new logger: log
160
200
 
201
+ ### Identifying running tasks with X-Opaque-Id
202
+
203
+ The X-Opaque-Id header allows to track certain calls, or associate certain tasks with the client that started them ([more on the Elasticsearch docs](https://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html#_identifying_running_tasks)). To use this feature, you need to set an id for `opaque_id` on the client on each request. Example:
204
+
205
+ ```ruby
206
+ client = Elasticsearch::Client.new
207
+ client.search(index: 'myindex', q: 'title:test', opaque_id: '123456')
208
+ ```
209
+ The search request will include the following HTTP Header:
210
+ ```
211
+ X-Opaque-Id: 123456
212
+ ```
213
+
214
+ You can also set a prefix for X-Opaque-Id when initializing the client. This will be prepended to the id you set before each request if you're using X-Opaque-Id. Example:
215
+ ```ruby
216
+ client = Elasticsearch::Client.new(opaque_id_prefix: 'eu-west1')
217
+ client.search(index: 'myindex', q: 'title:test', opaque_id: '123456')
218
+ ```
219
+ The request will include the following HTTP Header:
220
+ ```
221
+ X-Opaque-Id: eu-west1_123456
222
+ ```
223
+
161
224
  ### Setting Timeouts
162
225
 
163
226
  For many operations in Elasticsearch, the default timeouts of HTTP libraries are too low.
@@ -292,44 +355,35 @@ constructor, use the `transport_options` key:
292
355
 
293
356
  To configure the _Faraday_ instance directly, use a block:
294
357
 
295
- require 'typhoeus'
296
- require 'typhoeus/adapters/faraday'
358
+ require 'patron'
297
359
 
298
360
  client = Elasticsearch::Client.new(host: 'localhost', port: '9200') do |f|
299
361
  f.response :logger
300
- f.adapter :typhoeus
362
+ f.adapter :patron
301
363
  end
302
364
 
303
- You can use any standard Faraday middleware and plugins in the configuration block,
304
- for example sign the requests for the [AWS Elasticsearch service](https://aws.amazon.com/elasticsearch-service/):
305
-
306
- require 'faraday_middleware/aws_signers_v4'
307
-
308
- client = Elasticsearch::Client.new url: 'https://search-my-cluster-abc123....es.amazonaws.com' do |f|
309
- f.request :aws_signers_v4,
310
- credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY'], ENV['AWS_SECRET_ACCESS_KEY']),
311
- service_name: 'es',
312
- region: 'us-east-1'
313
- end
365
+ You can use any standard Faraday middleware and plugins in the configuration block, for example sign the requests for the [AWS Elasticsearch service](https://aws.amazon.com/elasticsearch-service/). See [the AWS documentation](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-request-signing.html#es-request-signing-ruby) for an example.
314
366
 
315
367
  You can also initialize the transport class yourself, and pass it to the client constructor
316
368
  as the `transport` argument:
317
369
 
318
- require 'typhoeus'
319
- require 'typhoeus/adapters/faraday'
370
+ ```ruby
371
+ require 'patron'
320
372
 
321
- transport_configuration = lambda do |f|
322
- f.response :logger
323
- f.adapter :typhoeus
324
- end
373
+ transport_configuration = lambda do |f|
374
+ f.response :logger
375
+ f.adapter :patron
376
+ end
325
377
 
326
- transport = Elasticsearch::Transport::Transport::HTTP::Faraday.new \
327
- hosts: [ { host: 'localhost', port: '9200' } ],
328
- &transport_configuration
378
+ transport = Elasticsearch::Transport::Transport::HTTP::Faraday.new \
379
+ hosts: [ { host: 'localhost', port: '9200' } ],
380
+ &transport_configuration
381
+
382
+ # Pass the transport to the client
383
+ #
384
+ client = Elasticsearch::Client.new transport: transport
385
+ ```
329
386
 
330
- # Pass the transport to the client
331
- #
332
- client = Elasticsearch::Client.new transport: transport
333
387
 
334
388
  Instead of passing the transport to the constructor, you can inject it at run time:
335
389
 
@@ -4,75 +4,55 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'elasticsearch/transport/version'
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = "elasticsearch-transport"
7
+ s.name = 'elasticsearch-transport'
8
8
  s.version = Elasticsearch::Transport::VERSION
9
- s.authors = ["Karel Minarik"]
10
- s.email = ["karel.minarik@elasticsearch.org"]
11
- s.summary = "Ruby client for Elasticsearch."
12
- s.homepage = "https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-transport"
13
- s.license = "Apache-2.0"
14
-
9
+ s.authors = ['Karel Minarik']
10
+ s.email = ['karel.minarik@elasticsearch.org']
11
+ s.summary = 'Ruby client for Elasticsearch.'
12
+ s.homepage = 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/current/index.html'
13
+ s.license = 'Apache-2.0'
14
+ s.metadata = {
15
+ 'homepage_uri' => 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/current/index.html',
16
+ 'changelog_uri' => 'https://github.com/elastic/elasticsearch-ruby/blob/6.x/CHANGELOG.md',
17
+ 'source_code_uri' => 'https://github.com/elastic/elasticsearch-ruby/tree/6.x/elasticsearch-transport',
18
+ 'bug_tracker_uri' => 'https://github.com/elastic/elasticsearch-ruby/issues'
19
+ }
15
20
  s.files = `git ls-files`.split($/)
16
21
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
22
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
- s.require_paths = ["lib"]
19
-
20
- s.extra_rdoc_files = [ "README.md", "LICENSE.txt" ]
21
- s.rdoc_options = [ "--charset=UTF-8" ]
22
-
23
- s.required_ruby_version = '>= 1.9'
24
-
25
- s.add_dependency "multi_json"
26
- s.add_dependency "faraday", '>= 0.14', "< 1"
27
-
28
- if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
29
- s.add_dependency "system_timer"
30
- end
31
-
32
- s.add_development_dependency "bundler"
33
-
34
- if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
35
- s.add_development_dependency "rake", "~> 11.1"
36
- else
37
- s.add_development_dependency "rake", "< 11.0"
38
- end
39
-
40
- if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
41
- s.add_development_dependency "elasticsearch-extensions"
42
- end
43
-
44
- s.add_development_dependency "ansi"
45
- s.add_development_dependency "shoulda-context"
46
- s.add_development_dependency "mocha"
47
- s.add_development_dependency "turn"
48
- s.add_development_dependency "yard"
49
- s.add_development_dependency "pry"
50
-
23
+ s.require_paths = ['lib']
24
+
25
+ s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
26
+ s.rdoc_options = ['--charset=UTF-8']
27
+
28
+ s.required_ruby_version = '>= 2.4'
29
+
30
+ s.add_dependency 'multi_json'
31
+ s.add_dependency 'faraday', '~> 1'
32
+ s.add_development_dependency 'ansi'
33
+ s.add_development_dependency 'bundler'
34
+ s.add_development_dependency 'elasticsearch-extensions'
35
+ s.add_development_dependency 'mocha'
36
+ s.add_development_dependency 'pry'
37
+ s.add_development_dependency 'rake', '~> 13'
38
+ s.add_development_dependency 'shoulda-context'
39
+ s.add_development_dependency 'turn'
40
+ s.add_development_dependency 'yard'
51
41
  # Gems for testing integrations
52
- s.add_development_dependency "curb" unless defined? JRUBY_VERSION
53
- s.add_development_dependency "patron" unless defined? JRUBY_VERSION
54
- s.add_development_dependency "typhoeus", '~> 0.6'
55
- s.add_development_dependency "net-http-persistent"
56
- s.add_development_dependency "manticore", '~> 0.5.2' if defined? JRUBY_VERSION
57
- s.add_development_dependency "hashie"
58
-
59
- # Prevent unit test failures on Ruby 1.8
60
- if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
61
- s.add_development_dependency "test-unit", '~> 2'
62
- s.add_development_dependency "json", '~> 1.8'
63
- end
64
-
65
- if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
66
- s.add_development_dependency "minitest", "~> 4.0"
67
- s.add_development_dependency "ruby-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
68
- s.add_development_dependency "require-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
69
- s.add_development_dependency "simplecov"
70
- s.add_development_dependency "simplecov-rcov"
71
- s.add_development_dependency "cane"
72
- end
73
-
74
- if defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
75
- s.add_development_dependency "test-unit", '~> 2'
42
+ s.add_development_dependency 'cane'
43
+ s.add_development_dependency 'hashie'
44
+ s.add_development_dependency 'manticore', '~> 0.5.2' if defined? JRUBY_VERSION
45
+ s.add_development_dependency 'minitest', '~> 4.0'
46
+ s.add_development_dependency 'net-http-persistent'
47
+ s.add_development_dependency 'simplecov', '~> 0.17', '< 0.18'
48
+ s.add_development_dependency 'simplecov-rcov'
49
+ s.add_development_dependency 'test-unit', '~> 2'
50
+ s.add_development_dependency 'typhoeus', '~> 0.6'
51
+ unless defined?(JRUBY_VERSION) || defined?(Rubinius)
52
+ s.add_development_dependency 'curb'
53
+ s.add_development_dependency 'patron'
54
+ s.add_development_dependency 'require-prof'
55
+ s.add_development_dependency 'ruby-prof'
76
56
  end
77
57
 
78
58
  s.description = <<-DESC.gsub(/^ /, '')
@@ -1 +1,5 @@
1
+ # Licensed to Elasticsearch B.V under one or more agreements.
2
+ # Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3
+ # See the LICENSE file in the project root for more information
4
+
1
5
  require 'elasticsearch/transport'
@@ -1,3 +1,7 @@
1
+ # Licensed to Elasticsearch B.V under one or more agreements.
2
+ # Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3
+ # See the LICENSE file in the project root for more information
4
+
1
5
  require "uri"
2
6
  require "time"
3
7
  require "timeout"
@@ -1,3 +1,7 @@
1
+ # Licensed to Elasticsearch B.V under one or more agreements.
2
+ # Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3
+ # See the LICENSE file in the project root for more information
4
+
1
5
  module Elasticsearch
2
6
  module Transport
3
7
 
@@ -85,6 +89,11 @@ module Elasticsearch
85
89
  # @option arguments [String] :send_get_body_as Specify the HTTP method to use for GET requests with a body.
86
90
  # (Default: GET)
87
91
  #
92
+ # @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key`
93
+ # joined by a colon as a String, or a hash with the `id` and `api_key` values.
94
+ # @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client. This
95
+ # will be prepended to the id you set before each request if you're using X-Opaque-Id
96
+ #
88
97
  # @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block
89
98
  #
90
99
  def initialize(arguments={}, &block)
@@ -100,7 +109,10 @@ module Elasticsearch
100
109
  @arguments[:http] ||= {}
101
110
  @options[:http] ||= {}
102
111
 
103
- @seeds = __extract_hosts(@arguments[:hosts] ||
112
+ set_api_key if (@api_key = @arguments[:api_key])
113
+
114
+
115
+ @seeds ||= __extract_hosts(@arguments[:hosts] ||
104
116
  @arguments[:host] ||
105
117
  @arguments[:url] ||
106
118
  @arguments[:urls] ||
@@ -108,9 +120,10 @@ module Elasticsearch
108
120
  DEFAULT_HOST)
109
121
 
110
122
  @send_get_body_as = @arguments[:send_get_body_as] || 'GET'
123
+ @opaque_id_prefix = @arguments[:opaque_id_prefix] || nil
111
124
 
112
125
  if @arguments[:request_timeout]
113
- @arguments[:transport_options][:request] = { :timeout => @arguments[:request_timeout] }
126
+ @arguments[:transport_options][:request] = { timeout: @arguments[:request_timeout] }
114
127
  end
115
128
 
116
129
  @arguments[:transport_options][:headers] ||= {}
@@ -124,27 +137,41 @@ module Elasticsearch
124
137
  else
125
138
  transport_class = @arguments[:transport_class] || DEFAULT_TRANSPORT_CLASS
126
139
  if transport_class == Transport::HTTP::Faraday
127
- @transport = transport_class.new(:hosts => @seeds, :options => @arguments) do |faraday|
128
- block.call faraday if block
129
- unless (h = faraday.builder.handlers.last) && h.name.start_with?("Faraday::Adapter")
130
- faraday.adapter(@arguments[:adapter] || __auto_detect_adapter)
131
- end
140
+ @transport = transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
141
+ faraday.adapter(@arguments[:adapter] || __auto_detect_adapter)
142
+ block&.call faraday
132
143
  end
133
144
  else
134
- @transport = transport_class.new(:hosts => @seeds, :options => @arguments)
145
+ @transport = transport_class.new(hosts: @seeds, options: @arguments)
135
146
  end
136
147
  end
137
148
  end
138
149
 
139
150
  # Performs a request through delegation to {#transport}.
140
151
  #
141
- def perform_request(method, path, params={}, body=nil, headers=nil)
152
+ def perform_request(method, path, params = {}, body = nil, headers = nil)
142
153
  method = @send_get_body_as if 'GET' == method && body
154
+ if (opaque_id = params.delete(:opaque_id))
155
+ headers = {} if headers.nil?
156
+ opaque_id = @opaque_id_prefix ? "#{@opaque_id_prefix}#{opaque_id}" : opaque_id
157
+ headers.merge!('X-Opaque-Id' => opaque_id)
158
+ end
143
159
  transport.perform_request(method, path, params, body, headers)
144
160
  end
145
161
 
146
162
  private
147
163
 
164
+ def set_api_key
165
+ @api_key = __encode(@api_key) if @api_key.is_a? Hash
166
+ headers = @arguments[:transport_options]&.[](:headers) || {}
167
+ headers.merge!('Authorization' => "ApiKey #{@api_key}")
168
+ @arguments[:transport_options].merge!(
169
+ headers: headers
170
+ )
171
+ @arguments.delete(:user)
172
+ @arguments.delete(:password)
173
+ end
174
+
148
175
  # Normalizes and returns hosts configuration.
149
176
  #
150
177
  # Arrayifies the `hosts_config` argument and extracts `host` and `port` info from strings.
@@ -202,8 +229,14 @@ module Elasticsearch
202
229
  raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
203
230
  end
204
231
 
205
- @options[:http][:user] ||= host_parts[:user]
206
- @options[:http][:password] ||= host_parts[:password]
232
+ if @api_key
233
+ # Remove Basic Auth if using API KEY
234
+ host_parts.delete(:user)
235
+ host_parts.delete(:password)
236
+ else
237
+ @options[:http][:user] ||= host_parts[:user]
238
+ @options[:http][:password] ||= host_parts[:password]
239
+ end
207
240
 
208
241
  host_parts[:port] = host_parts[:port].to_i if host_parts[:port]
209
242
  host_parts[:path].chomp!('/') if host_parts[:path]
@@ -232,6 +265,13 @@ module Elasticsearch
232
265
  ::Faraday.default_adapter
233
266
  end
234
267
  end
268
+
269
+ # Encode credentials for the Authorization Header
270
+ # Credentials is the base64 encoding of id and api_key joined by a colon
271
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
272
+ def __encode(api_key)
273
+ Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':'))
274
+ end
235
275
  end
236
276
  end
237
277
  end
@@ -1,3 +1,7 @@
1
+ # Licensed to Elasticsearch B.V under one or more agreements.
2
+ # Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3
+ # See the LICENSE file in the project root for more information
4
+
1
5
  # Licensed to Elasticsearch B.V. under one or more contributor
2
6
  # license agreements. See the NOTICE file distributed with
3
7
  # this work for additional information regarding copyright
@@ -1,3 +1,7 @@
1
+ # Licensed to Elasticsearch B.V under one or more agreements.
2
+ # Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3
+ # See the LICENSE file in the project root for more information
4
+
1
5
  module Elasticsearch
2
6
  module Transport
3
7
  module Transport
@@ -16,7 +20,7 @@ module Elasticsearch
16
20
  attr_reader :hosts, :options, :connections, :counter, :last_request_at, :protocol
17
21
  attr_accessor :serializer, :sniffer, :logger, :tracer,
18
22
  :reload_connections, :reload_after,
19
- :resurrect_after, :max_retries
23
+ :resurrect_after
20
24
 
21
25
  # Creates a new transport object
22
26
  #
@@ -52,7 +56,6 @@ module Elasticsearch
52
56
  @reload_connections = options[:reload_connections]
53
57
  @reload_after = options[:reload_connections].is_a?(Integer) ? options[:reload_connections] : DEFAULT_RELOAD_AFTER
54
58
  @resurrect_after = options[:resurrect_after] || DEFAULT_RESURRECT_AFTER
55
- @max_retries = options[:retry_on_failure].is_a?(Integer) ? options[:retry_on_failure] : DEFAULT_MAX_RETRIES
56
59
  @retry_on_status = Array(options[:retry_on_status]).map { |d| d.to_i }
57
60
  end
58
61
 
@@ -244,10 +247,17 @@ module Elasticsearch
244
247
  # @raise [ServerError] If request failed on server
245
248
  # @raise [Error] If no connection is available
246
249
  #
247
- def perform_request(method, path, params={}, body=nil, headers=nil, &block)
250
+ def perform_request(method, path, params={}, body=nil, headers=nil, opts={}, &block)
248
251
  raise NoMethodError, "Implement this method in your transport class" unless block_given?
249
252
  start = Time.now if logger || tracer
250
253
  tries = 0
254
+ reload_on_failure = opts.fetch(:reload_on_failure, @options[:reload_on_failure])
255
+
256
+ max_retries = if opts.key?(:retry_on_failure)
257
+ opts[:retry_on_failure] === true ? DEFAULT_MAX_RETRIES : opts[:retry_on_failure]
258
+ elsif options.key?(:retry_on_failure)
259
+ options[:retry_on_failure] === true ? DEFAULT_MAX_RETRIES : options[:retry_on_failure]
260
+ end
251
261
 
252
262
  params = params.clone
253
263
 
@@ -271,9 +281,9 @@ module Elasticsearch
271
281
  __raise_transport_error(response) if response.status.to_i >= 300 && @retry_on_status.include?(response.status.to_i)
272
282
 
273
283
  rescue Elasticsearch::Transport::Transport::ServerError => e
274
- if @retry_on_status.include?(response.status)
284
+ if response && @retry_on_status.include?(response.status)
275
285
  logger.warn "[#{e.class}] Attempt #{tries} to get response from #{url}" if logger
276
- if tries <= max_retries
286
+ if tries <= (max_retries || DEFAULT_MAX_RETRIES)
277
287
  retry
278
288
  else
279
289
  logger.fatal "[#{e.class}] Cannot get response from #{url} after #{tries} tries" if logger
@@ -288,12 +298,12 @@ module Elasticsearch
288
298
 
289
299
  connection.dead!
290
300
 
291
- if @options[:reload_on_failure] and tries < connections.all.size
301
+ if reload_on_failure and tries < connections.all.size
292
302
  logger.warn "[#{e.class}] Reloading connections (attempt #{tries} of #{connections.all.size})" if logger
293
303
  reload_connections! and retry
294
304
  end
295
305
 
296
- if @options[:retry_on_failure]
306
+ if max_retries
297
307
  logger.warn "[#{e.class}] Attempt #{tries} connecting to #{connection.host.inspect}" if logger
298
308
  if tries <= max_retries
299
309
  retry