elasticsearch-transport 5.0.5 → 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.
- checksums.yaml +5 -5
- data/Gemfile +5 -0
- data/README.md +88 -34
- data/Rakefile +14 -17
- data/elasticsearch-transport.gemspec +44 -63
- data/lib/elasticsearch/transport/client.rb +120 -61
- data/lib/elasticsearch/transport/redacted.rb +79 -0
- data/lib/elasticsearch/transport/transport/base.rb +28 -14
- data/lib/elasticsearch/transport/transport/connections/collection.rb +4 -0
- data/lib/elasticsearch/transport/transport/connections/connection.rb +5 -1
- data/lib/elasticsearch/transport/transport/connections/selector.rb +4 -0
- data/lib/elasticsearch/transport/transport/errors.rb +4 -0
- data/lib/elasticsearch/transport/transport/http/curb.rb +7 -2
- data/lib/elasticsearch/transport/transport/http/faraday.rb +11 -8
- data/lib/elasticsearch/transport/transport/http/manticore.rb +6 -1
- data/lib/elasticsearch/transport/transport/response.rb +4 -0
- data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +4 -0
- data/lib/elasticsearch/transport/transport/sniffer.rb +31 -3
- data/lib/elasticsearch/transport/version.rb +5 -1
- data/lib/elasticsearch/transport.rb +5 -0
- data/lib/elasticsearch-transport.rb +4 -0
- data/spec/elasticsearch/transport/base_spec.rb +260 -0
- data/spec/elasticsearch/transport/client_spec.rb +1025 -0
- data/spec/elasticsearch/transport/sniffer_spec.rb +269 -0
- data/spec/spec_helper.rb +65 -0
- data/test/integration/transport_test.rb +9 -5
- data/test/profile/client_benchmark_test.rb +23 -25
- data/test/test_helper.rb +10 -0
- data/test/unit/connection_collection_test.rb +4 -0
- data/test/unit/connection_selector_test.rb +4 -0
- data/test/unit/connection_test.rb +4 -0
- data/test/unit/response_test.rb +5 -1
- data/test/unit/serializer_test.rb +4 -0
- data/test/unit/transport_base_test.rb +21 -1
- data/test/unit/transport_curb_test.rb +12 -0
- data/test/unit/transport_faraday_test.rb +16 -0
- data/test/unit/transport_manticore_test.rb +11 -0
- metadata +82 -84
- data/test/integration/client_test.rb +0 -237
- data/test/unit/client_test.rb +0 -366
- data/test/unit/sniffer_test.rb +0 -179
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c036b32f60221fef3a8c617ddc30a55c50c916b4f3c235fe34f91917060c9ae4
|
4
|
+
data.tar.gz: 18d4582f2c6479fe2af5bf10a6f6cc97d6083172274be5de85d82a47f62b1a04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a06a56942b78b094e562ef1fa4d6adfd9433a823aeb3e21e06296574c39bcb5c228b52a009fe3a375a8682a1d0e9c9d370ff74a5a84dce4d2800170ede4e3d5c
|
7
|
+
data.tar.gz: 8646819dd552fae0bbba12d03e0a2ed1c996f2d0493a0ad65c4f07bd5e2ae763d8067aefc66c8d52963def632d1a552c7271744233ba12a5b43945d281800d1c
|
data/Gemfile
CHANGED
@@ -14,3 +14,8 @@ end
|
|
14
14
|
if File.exist? File.expand_path("../../elasticsearch/elasticsearch.gemspec", __FILE__)
|
15
15
|
gem 'elasticsearch', :path => File.expand_path("../../elasticsearch", __FILE__), :require => false
|
16
16
|
end
|
17
|
+
|
18
|
+
group :development do
|
19
|
+
gem 'rspec'
|
20
|
+
gem 'pry-nav'
|
21
|
+
end
|
data/README.md
CHANGED
@@ -16,24 +16,28 @@ data serialization and transport.
|
|
16
16
|
It does not handle calling the Elasticsearch API;
|
17
17
|
see the [`elasticsearch-api`](https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-api) library.
|
18
18
|
|
19
|
-
The library is compatible with Ruby 1.
|
19
|
+
The library is compatible with Ruby 1.9 or higher and with all versions of Elasticsearch since 0.90.
|
20
20
|
|
21
21
|
Features overview:
|
22
22
|
|
23
23
|
* Pluggable logging and tracing
|
24
|
-
*
|
24
|
+
* Pluggable connection selection strategies (round-robin, random, custom)
|
25
25
|
* Pluggable transport implementation, customizable and extendable
|
26
26
|
* Pluggable serializer implementation
|
27
27
|
* Request retries and dead connections handling
|
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 [
|
32
|
-
Just require the library (`require '
|
33
|
-
and it will be automatically used
|
34
|
-
|
35
|
-
|
36
|
-
[
|
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 '
|
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 :
|
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
|
-
|
319
|
-
|
370
|
+
```ruby
|
371
|
+
require 'patron'
|
320
372
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
373
|
+
transport_configuration = lambda do |f|
|
374
|
+
f.response :logger
|
375
|
+
f.adapter :patron
|
376
|
+
end
|
325
377
|
|
326
|
-
|
327
|
-
|
328
|
-
|
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
|
|
data/Rakefile
CHANGED
@@ -7,40 +7,37 @@ task :test => 'test:unit'
|
|
7
7
|
# ----- Test tasks ------------------------------------------------------------
|
8
8
|
|
9
9
|
require 'rake/testtask'
|
10
|
+
require 'rspec/core/rake_task'
|
11
|
+
|
10
12
|
namespace :test do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
require 'ci/reporter/rake/minitest'
|
18
|
-
Rake::Task['ci:setup:minitest'].invoke
|
19
|
-
end
|
13
|
+
|
14
|
+
RSpec::Core::RakeTask.new(:spec)
|
15
|
+
|
16
|
+
desc "Wait for Elasticsearch to be in a green state"
|
17
|
+
task :wait_for_green do
|
18
|
+
sh '../scripts/wait-cluster.sh'
|
20
19
|
end
|
21
20
|
|
22
21
|
Rake::TestTask.new(:unit) do |test|
|
23
|
-
Rake::Task['test:ci_reporter'].invoke if ENV['CI']
|
24
22
|
test.libs << 'lib' << 'test'
|
25
23
|
test.test_files = FileList["test/unit/**/*_test.rb"]
|
26
|
-
|
27
|
-
|
24
|
+
test.verbose = false
|
25
|
+
test.warning = false
|
28
26
|
end
|
29
27
|
|
30
28
|
Rake::TestTask.new(:integration) do |test|
|
31
|
-
Rake::Task['test:ci_reporter'].invoke if ENV['CI']
|
32
29
|
test.libs << 'lib' << 'test'
|
33
30
|
test.test_files = FileList["test/integration/**/*_test.rb"]
|
31
|
+
test.deps = [ :wait_for_green, :spec ]
|
32
|
+
test.verbose = false
|
33
|
+
test.warning = false
|
34
34
|
end
|
35
35
|
|
36
36
|
Rake::TestTask.new(:all) do |test|
|
37
|
-
|
38
|
-
test.libs << 'lib' << 'test'
|
39
|
-
test.test_files = FileList["test/unit/**/*_test.rb", "test/integration/**/*_test.rb"]
|
37
|
+
test.deps = [ :unit, :integration ]
|
40
38
|
end
|
41
39
|
|
42
40
|
Rake::TestTask.new(:profile) do |test|
|
43
|
-
Rake::Task['test:ci_reporter'].invoke if ENV['CI']
|
44
41
|
test.libs << 'lib' << 'test'
|
45
42
|
test.test_files = FileList["test/profile/**/*_test.rb"]
|
46
43
|
end
|
@@ -4,74 +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 =
|
7
|
+
s.name = 'elasticsearch-transport'
|
8
8
|
s.version = Elasticsearch::Transport::VERSION
|
9
|
-
s.authors = [
|
10
|
-
s.email = [
|
11
|
-
s.summary =
|
12
|
-
s.homepage =
|
13
|
-
s.license =
|
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 = [
|
19
|
-
|
20
|
-
s.extra_rdoc_files = [
|
21
|
-
s.rdoc_options = [
|
22
|
-
|
23
|
-
s.
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
s.add_development_dependency
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
|
39
|
-
s.add_development_dependency "elasticsearch-extensions"
|
40
|
-
end
|
41
|
-
|
42
|
-
s.add_development_dependency "ansi"
|
43
|
-
s.add_development_dependency "shoulda-context"
|
44
|
-
s.add_development_dependency "mocha"
|
45
|
-
s.add_development_dependency "turn"
|
46
|
-
s.add_development_dependency "yard"
|
47
|
-
s.add_development_dependency "pry"
|
48
|
-
s.add_development_dependency "ci_reporter", "~> 1.9"
|
49
|
-
|
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'
|
50
41
|
# Gems for testing integrations
|
51
|
-
s.add_development_dependency
|
52
|
-
s.add_development_dependency
|
53
|
-
s.add_development_dependency
|
54
|
-
s.add_development_dependency
|
55
|
-
s.add_development_dependency
|
56
|
-
s.add_development_dependency
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
s.add_development_dependency
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
s.add_development_dependency "minitest", "~> 4.0"
|
66
|
-
s.add_development_dependency "ruby-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
67
|
-
s.add_development_dependency "require-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
68
|
-
s.add_development_dependency "simplecov"
|
69
|
-
s.add_development_dependency "simplecov-rcov"
|
70
|
-
s.add_development_dependency "cane"
|
71
|
-
end
|
72
|
-
|
73
|
-
if defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
|
74
|
-
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'
|
75
56
|
end
|
76
57
|
|
77
58
|
s.description = <<-DESC.gsub(/^ /, '')
|
@@ -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
|
|
@@ -24,6 +28,11 @@ module Elasticsearch
|
|
24
28
|
logger
|
25
29
|
end
|
26
30
|
|
31
|
+
# The default host and port to use if not otherwise specified.
|
32
|
+
#
|
33
|
+
# @since 7.0.0
|
34
|
+
DEFAULT_HOST = 'localhost:9200'.freeze
|
35
|
+
|
27
36
|
# Returns the transport object.
|
28
37
|
#
|
29
38
|
# @see Elasticsearch::Transport::Transport::Base
|
@@ -80,17 +89,16 @@ module Elasticsearch
|
|
80
89
|
# @option arguments [String] :send_get_body_as Specify the HTTP method to use for GET requests with a body.
|
81
90
|
# (Default: GET)
|
82
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
|
+
#
|
83
97
|
# @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block
|
84
98
|
#
|
85
99
|
def initialize(arguments={}, &block)
|
100
|
+
@options = arguments
|
86
101
|
@arguments = arguments
|
87
|
-
|
88
|
-
hosts = @arguments[:hosts] || \
|
89
|
-
@arguments[:host] || \
|
90
|
-
@arguments[:url] || \
|
91
|
-
@arguments[:urls] || \
|
92
|
-
ENV.fetch('ELASTICSEARCH_URL', 'localhost:9200')
|
93
|
-
|
94
102
|
@arguments[:logger] ||= @arguments[:log] ? DEFAULT_LOGGER.call() : nil
|
95
103
|
@arguments[:tracer] ||= @arguments[:trace] ? DEFAULT_TRACER.call() : nil
|
96
104
|
@arguments[:reload_connections] ||= false
|
@@ -99,36 +107,69 @@ module Elasticsearch
|
|
99
107
|
@arguments[:randomize_hosts] ||= false
|
100
108
|
@arguments[:transport_options] ||= {}
|
101
109
|
@arguments[:http] ||= {}
|
110
|
+
@options[:http] ||= {}
|
102
111
|
|
103
|
-
|
112
|
+
set_api_key if (@api_key = @arguments[:api_key])
|
104
113
|
|
105
|
-
|
106
|
-
@
|
114
|
+
|
115
|
+
@seeds ||= __extract_hosts(@arguments[:hosts] ||
|
116
|
+
@arguments[:host] ||
|
117
|
+
@arguments[:url] ||
|
118
|
+
@arguments[:urls] ||
|
119
|
+
ENV['ELASTICSEARCH_URL'] ||
|
120
|
+
DEFAULT_HOST)
|
107
121
|
|
108
122
|
@send_get_body_as = @arguments[:send_get_body_as] || 'GET'
|
123
|
+
@opaque_id_prefix = @arguments[:opaque_id_prefix] || nil
|
109
124
|
|
110
|
-
|
125
|
+
if @arguments[:request_timeout]
|
126
|
+
@arguments[:transport_options][:request] = { timeout: @arguments[:request_timeout] }
|
127
|
+
end
|
128
|
+
|
129
|
+
@arguments[:transport_options][:headers] ||= {}
|
111
130
|
|
112
|
-
|
131
|
+
unless @arguments[:transport_options][:headers].keys.any? {|k| k.to_s.downcase =~ /content\-?\_?type/}
|
132
|
+
@arguments[:transport_options][:headers]['Content-Type'] = 'application/json'
|
133
|
+
end
|
134
|
+
|
135
|
+
if @arguments[:transport]
|
136
|
+
@transport = @arguments[:transport]
|
137
|
+
else
|
138
|
+
transport_class = @arguments[:transport_class] || DEFAULT_TRANSPORT_CLASS
|
113
139
|
if transport_class == Transport::HTTP::Faraday
|
114
|
-
transport_class.new(:
|
115
|
-
|
116
|
-
|
117
|
-
faraday.adapter(@arguments[:adapter] || __auto_detect_adapter)
|
118
|
-
end
|
140
|
+
@transport = transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
|
141
|
+
faraday.adapter(@arguments[:adapter] || __auto_detect_adapter)
|
142
|
+
block&.call faraday
|
119
143
|
end
|
120
144
|
else
|
121
|
-
transport_class.new(:
|
145
|
+
@transport = transport_class.new(hosts: @seeds, options: @arguments)
|
122
146
|
end
|
123
147
|
end
|
124
148
|
end
|
125
149
|
|
126
150
|
# Performs a request through delegation to {#transport}.
|
127
151
|
#
|
128
|
-
def perform_request(method, path, params={}, body=nil)
|
152
|
+
def perform_request(method, path, params = {}, body = nil, headers = nil)
|
129
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
|
159
|
+
transport.perform_request(method, path, params, body, headers)
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
130
163
|
|
131
|
-
|
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)
|
132
173
|
end
|
133
174
|
|
134
175
|
# Normalizes and returns hosts configuration.
|
@@ -143,52 +184,63 @@ module Elasticsearch
|
|
143
184
|
#
|
144
185
|
# @api private
|
145
186
|
#
|
146
|
-
def __extract_hosts(hosts_config
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
result = hosts.map do |host|
|
158
|
-
host_parts = case host
|
159
|
-
when String
|
160
|
-
if host =~ /^[a-z]+\:\/\//
|
161
|
-
uri = URI.parse(host)
|
162
|
-
{ :scheme => uri.scheme, :user => uri.user, :password => uri.password, :host => uri.host, :path => uri.path, :port => uri.port }
|
163
|
-
else
|
164
|
-
host, port = host.split(':')
|
165
|
-
{ :host => host, :port => port }
|
166
|
-
end
|
167
|
-
when URI
|
168
|
-
{ :scheme => host.scheme, :user => host.user, :password => host.password, :host => host.host, :path => host.path, :port => host.port }
|
169
|
-
when Hash
|
170
|
-
host
|
171
|
-
else
|
172
|
-
raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
|
173
|
-
end
|
174
|
-
|
175
|
-
host_parts[:port] = host_parts[:port].to_i unless host_parts[:port].nil?
|
187
|
+
def __extract_hosts(hosts_config)
|
188
|
+
hosts = case hosts_config
|
189
|
+
when String
|
190
|
+
hosts_config.split(',').map { |h| h.strip! || h }
|
191
|
+
when Array
|
192
|
+
hosts_config
|
193
|
+
when Hash, URI
|
194
|
+
[ hosts_config ]
|
195
|
+
else
|
196
|
+
Array(hosts_config)
|
197
|
+
end
|
176
198
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
host_parts.select { |k,v| [:scheme, :port, :user, :password].include?(k) }.each do |k,v|
|
181
|
-
@arguments[:http][k] ||= v
|
182
|
-
end
|
199
|
+
host_list = hosts.map { |host| __parse_host(host) }
|
200
|
+
@options[:randomize_hosts] ? host_list.shuffle! : host_list
|
201
|
+
end
|
183
202
|
|
184
|
-
|
185
|
-
|
203
|
+
def __parse_host(host)
|
204
|
+
host_parts = case host
|
205
|
+
when String
|
206
|
+
if host =~ /^[a-z]+\:\/\//
|
207
|
+
uri = URI.parse(host)
|
208
|
+
{ :scheme => uri.scheme,
|
209
|
+
:user => uri.user,
|
210
|
+
:password => uri.password,
|
211
|
+
:host => uri.host,
|
212
|
+
:path => uri.path,
|
213
|
+
:port => uri.port }
|
214
|
+
else
|
215
|
+
host, port = host.split(':')
|
216
|
+
{ :host => host,
|
217
|
+
:port => port }
|
218
|
+
end
|
219
|
+
when URI
|
220
|
+
{ :scheme => host.scheme,
|
221
|
+
:user => host.user,
|
222
|
+
:password => host.password,
|
223
|
+
:host => host.host,
|
224
|
+
:path => host.path,
|
225
|
+
:port => host.port }
|
226
|
+
when Hash
|
227
|
+
host
|
228
|
+
else
|
229
|
+
raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
|
230
|
+
end
|
186
231
|
|
187
|
-
|
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]
|
188
239
|
end
|
189
240
|
|
190
|
-
|
191
|
-
|
241
|
+
host_parts[:port] = host_parts[:port].to_i if host_parts[:port]
|
242
|
+
host_parts[:path].chomp!('/') if host_parts[:path]
|
243
|
+
host_parts
|
192
244
|
end
|
193
245
|
|
194
246
|
# Auto-detect the best adapter (HTTP "driver") available, based on libraries
|
@@ -213,6 +265,13 @@ module Elasticsearch
|
|
213
265
|
::Faraday.default_adapter
|
214
266
|
end
|
215
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
|
216
275
|
end
|
217
276
|
end
|
218
277
|
end
|