elasticsearch-transport 6.8.1 → 6.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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