elasticsearch-transport 7.4.0 → 7.17.10
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 +4 -4
- data/Gemfile +30 -13
- data/Gemfile-faraday1.gemfile +47 -0
- data/README.md +159 -64
- data/Rakefile +63 -13
- data/elasticsearch-transport.gemspec +55 -63
- data/lib/elasticsearch/transport/client.rb +184 -59
- data/lib/elasticsearch/transport/meta_header.rb +135 -0
- data/lib/elasticsearch/transport/redacted.rb +16 -3
- data/lib/elasticsearch/transport/transport/base.rb +69 -30
- data/lib/elasticsearch/transport/transport/connections/collection.rb +18 -8
- data/lib/elasticsearch/transport/transport/connections/connection.rb +25 -9
- data/lib/elasticsearch/transport/transport/connections/selector.rb +16 -3
- data/lib/elasticsearch/transport/transport/errors.rb +17 -3
- data/lib/elasticsearch/transport/transport/http/curb.rb +60 -35
- data/lib/elasticsearch/transport/transport/http/faraday.rb +32 -9
- data/lib/elasticsearch/transport/transport/http/manticore.rb +57 -32
- data/lib/elasticsearch/transport/transport/loggable.rb +16 -3
- data/lib/elasticsearch/transport/transport/response.rb +17 -5
- data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +16 -3
- data/lib/elasticsearch/transport/transport/sniffer.rb +35 -15
- data/lib/elasticsearch/transport/version.rb +17 -4
- data/lib/elasticsearch/transport.rb +35 -33
- data/lib/elasticsearch-transport.rb +16 -3
- data/spec/elasticsearch/connections/collection_spec.rb +28 -3
- data/spec/elasticsearch/connections/selector_spec.rb +16 -3
- data/spec/elasticsearch/transport/base_spec.rb +107 -49
- data/spec/elasticsearch/transport/client_spec.rb +734 -164
- data/spec/elasticsearch/transport/http/curb_spec.rb +126 -0
- data/spec/elasticsearch/transport/http/faraday_spec.rb +141 -0
- data/spec/elasticsearch/transport/http/manticore_spec.rb +161 -0
- data/spec/elasticsearch/transport/meta_header_spec.rb +301 -0
- data/spec/elasticsearch/transport/sniffer_spec.rb +16 -16
- data/spec/spec_helper.rb +32 -6
- data/test/integration/jruby_test.rb +43 -0
- data/test/integration/transport_test.rb +109 -46
- data/test/profile/client_benchmark_test.rb +16 -3
- data/test/test_helper.rb +26 -25
- data/test/unit/adapters_test.rb +88 -0
- data/test/unit/connection_test.rb +23 -5
- data/test/unit/response_test.rb +18 -5
- data/test/unit/serializer_test.rb +16 -3
- data/test/unit/transport_base_test.rb +33 -11
- data/test/unit/transport_curb_test.rb +16 -4
- data/test/unit/transport_faraday_test.rb +18 -5
- data/test/unit/transport_manticore_test.rb +258 -158
- metadata +64 -76
@@ -1,6 +1,19 @@
|
|
1
|
-
# Licensed to Elasticsearch B.V under one or more
|
2
|
-
#
|
3
|
-
#
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
4
17
|
|
5
18
|
# coding: utf-8
|
6
19
|
lib = File.expand_path('../lib', __FILE__)
|
@@ -8,74 +21,53 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
8
21
|
require 'elasticsearch/transport/version'
|
9
22
|
|
10
23
|
Gem::Specification.new do |s|
|
11
|
-
s.name =
|
24
|
+
s.name = 'elasticsearch-transport'
|
12
25
|
s.version = Elasticsearch::Transport::VERSION
|
13
|
-
s.authors = [
|
14
|
-
s.email = [
|
15
|
-
s.summary =
|
16
|
-
s.homepage =
|
17
|
-
s.license =
|
18
|
-
|
26
|
+
s.authors = ['Karel Minarik']
|
27
|
+
s.email = ['karel.minarik@elasticsearch.org']
|
28
|
+
s.summary = 'Ruby client for Elasticsearch.'
|
29
|
+
s.homepage = 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.16/index.html'
|
30
|
+
s.license = 'Apache-2.0'
|
31
|
+
s.metadata = {
|
32
|
+
'homepage_uri' => 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.16/index.html',
|
33
|
+
'changelog_uri' => 'https://github.com/elastic/elasticsearch-ruby/blob/7.16/CHANGELOG.md',
|
34
|
+
'source_code_uri' => 'https://github.com/elastic/elasticsearch-ruby/tree/7.16/elasticsearch-transport',
|
35
|
+
'bug_tracker_uri' => 'https://github.com/elastic/elasticsearch-ruby/issues'
|
36
|
+
}
|
19
37
|
s.files = `git ls-files`.split($/)
|
20
38
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
39
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
22
|
-
s.require_paths = [
|
23
|
-
|
24
|
-
s.extra_rdoc_files = [ "README.md", "LICENSE" ]
|
25
|
-
s.rdoc_options = [ "--charset=UTF-8" ]
|
26
|
-
|
27
|
-
s.required_ruby_version = '>= 1.9'
|
28
|
-
|
29
|
-
s.add_dependency "multi_json"
|
30
|
-
s.add_dependency "faraday"
|
31
|
-
|
32
|
-
if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
|
33
|
-
s.add_dependency "system_timer"
|
34
|
-
end
|
35
|
-
|
36
|
-
s.add_development_dependency "bundler"
|
37
|
-
|
38
|
-
if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
|
39
|
-
s.add_development_dependency "rake", "~> 11.1"
|
40
|
-
else
|
41
|
-
s.add_development_dependency "rake", "< 11.0"
|
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 "yard"
|
48
|
-
s.add_development_dependency "pry"
|
40
|
+
s.require_paths = ['lib']
|
49
41
|
|
50
|
-
|
51
|
-
s.
|
52
|
-
s.add_development_dependency "patron" unless defined? JRUBY_VERSION
|
53
|
-
s.add_development_dependency "typhoeus", '~> 0.6'
|
54
|
-
s.add_development_dependency "net-http-persistent"
|
55
|
-
s.add_development_dependency "httpclient"
|
56
|
-
s.add_development_dependency "manticore", '~> 0.6' if defined? JRUBY_VERSION
|
57
|
-
s.add_development_dependency "hashie"
|
42
|
+
s.extra_rdoc_files = [ 'README.md', 'LICENSE' ]
|
43
|
+
s.rdoc_options = [ '--charset=UTF-8' ]
|
58
44
|
|
59
|
-
|
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
|
45
|
+
s.required_ruby_version = '>= 2.4'
|
64
46
|
|
65
|
-
|
66
|
-
|
67
|
-
s.add_development_dependency "minitest-reporters"
|
68
|
-
s.add_development_dependency "elasticsearch-extensions"
|
69
|
-
s.add_development_dependency "ruby-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
70
|
-
s.add_development_dependency "require-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
71
|
-
s.add_development_dependency "simplecov"
|
72
|
-
s.add_development_dependency "simplecov-rcov"
|
73
|
-
s.add_development_dependency "cane"
|
74
|
-
end
|
47
|
+
s.add_dependency 'multi_json'
|
48
|
+
s.add_dependency 'faraday', '>= 1', '< 3'
|
75
49
|
|
76
|
-
|
77
|
-
|
78
|
-
|
50
|
+
# Faraday Adapters
|
51
|
+
s.add_development_dependency 'manticore' if defined? JRUBY_VERSION
|
52
|
+
s.add_development_dependency 'curb' unless defined? JRUBY_VERSION
|
53
|
+
s.add_development_dependency 'ansi'
|
54
|
+
s.add_development_dependency 'bundler'
|
55
|
+
s.add_development_dependency 'cane'
|
56
|
+
s.add_development_dependency 'elasticsearch', ['>= 7', '< 8.0.0']
|
57
|
+
s.add_development_dependency 'elasticsearch-extensions'
|
58
|
+
s.add_development_dependency 'hashie'
|
59
|
+
s.add_development_dependency 'minitest'
|
60
|
+
s.add_development_dependency 'minitest-reporters'
|
61
|
+
s.add_development_dependency 'mocha'
|
62
|
+
s.add_development_dependency 'patron' unless defined? JRUBY_VERSION
|
63
|
+
s.add_development_dependency 'pry'
|
64
|
+
s.add_development_dependency 'rake', '~> 13'
|
65
|
+
s.add_development_dependency 'require-prof' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
66
|
+
s.add_development_dependency 'ruby-prof' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
67
|
+
s.add_development_dependency 'shoulda-context'
|
68
|
+
s.add_development_dependency 'simplecov'
|
69
|
+
s.add_development_dependency 'test-unit', '~> 2'
|
70
|
+
s.add_development_dependency 'yard'
|
79
71
|
|
80
72
|
s.description = <<-DESC.gsub(/^ /, '')
|
81
73
|
Ruby client for Elasticsearch. See the `elasticsearch` gem for full integration.
|
@@ -1,18 +1,32 @@
|
|
1
|
-
# Licensed to Elasticsearch B.V under one or more
|
2
|
-
#
|
3
|
-
#
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
4
17
|
|
5
18
|
require 'base64'
|
19
|
+
require 'elasticsearch/transport/meta_header'
|
6
20
|
|
7
21
|
module Elasticsearch
|
8
22
|
module Transport
|
9
|
-
|
10
23
|
# Handles communication with an Elasticsearch cluster.
|
11
24
|
#
|
12
25
|
# See {file:README.md README} for usage and code examples.
|
13
26
|
#
|
14
27
|
class Client
|
15
|
-
|
28
|
+
include MetaHeader
|
29
|
+
DEFAULT_TRANSPORT_CLASS = Transport::HTTP::Faraday
|
16
30
|
|
17
31
|
DEFAULT_LOGGER = lambda do
|
18
32
|
require 'logger'
|
@@ -36,9 +50,15 @@ module Elasticsearch
|
|
36
50
|
DEFAULT_HOST = 'localhost:9200'.freeze
|
37
51
|
|
38
52
|
# The default port to use if connecting using a Cloud ID.
|
53
|
+
# Updated from 9243 to 443 in client version 7.10.1
|
39
54
|
#
|
40
55
|
# @since 7.2.0
|
41
|
-
DEFAULT_CLOUD_PORT =
|
56
|
+
DEFAULT_CLOUD_PORT = 443
|
57
|
+
|
58
|
+
# The default port to use if not otherwise specified.
|
59
|
+
#
|
60
|
+
# @since 7.2.0
|
61
|
+
DEFAULT_PORT = 9200
|
42
62
|
|
43
63
|
# Returns the transport object.
|
44
64
|
#
|
@@ -72,6 +92,8 @@ module Elasticsearch
|
|
72
92
|
#
|
73
93
|
# @option arguments [Boolean,Number] :retry_on_failure Retry X times when request fails before raising and
|
74
94
|
# exception (false by default)
|
95
|
+
# @option arguments [Number] :delay_on_retry Delay in milliseconds between each retry (0 by default)
|
96
|
+
#
|
75
97
|
# @option arguments Array<Number> :retry_on_status Retry when specific status codes are returned
|
76
98
|
#
|
77
99
|
# @option arguments [Boolean] :reload_on_failure Reload connections after failure (false by default)
|
@@ -99,6 +121,15 @@ module Elasticsearch
|
|
99
121
|
# The default is false. Responses will automatically be inflated if they are compressed.
|
100
122
|
# If a custom transport object is used, it must handle the request compression and response inflation.
|
101
123
|
#
|
124
|
+
# @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key`
|
125
|
+
# joined by a colon as a String, or a hash with the `id` and `api_key` values.
|
126
|
+
# @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client.
|
127
|
+
# This will be prepended to the id you set before each request
|
128
|
+
# if you're using X-Opaque-Id
|
129
|
+
# @option enable_meta_header [Boolean] :enable_meta_header Enable sending the meta data header to Cloud.
|
130
|
+
# (Default: true)
|
131
|
+
# @option ca_fingerprint [String] :ca_fingerprint provide this value to only trust certificates that are signed by a specific CA certificate
|
132
|
+
#
|
102
133
|
# @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block
|
103
134
|
#
|
104
135
|
def initialize(arguments={}, &block)
|
@@ -108,61 +139,140 @@ module Elasticsearch
|
|
108
139
|
@arguments[:tracer] ||= @arguments[:trace] ? DEFAULT_TRACER.call() : nil
|
109
140
|
@arguments[:reload_connections] ||= false
|
110
141
|
@arguments[:retry_on_failure] ||= false
|
142
|
+
@arguments[:delay_on_retry] ||= 0
|
111
143
|
@arguments[:reload_on_failure] ||= false
|
112
144
|
@arguments[:randomize_hosts] ||= false
|
113
145
|
@arguments[:transport_options] ||= {}
|
114
146
|
@arguments[:http] ||= {}
|
115
|
-
@
|
147
|
+
@arguments[:enable_meta_header] = arguments.fetch(:enable_meta_header) { true }
|
148
|
+
@options[:http] ||= {}
|
149
|
+
|
150
|
+
set_api_key if (@api_key = @arguments[:api_key])
|
151
|
+
set_compatibility_header if ENV['ELASTIC_CLIENT_APIVERSIONING']
|
116
152
|
|
117
153
|
@seeds = extract_cloud_creds(@arguments)
|
118
154
|
@seeds ||= __extract_hosts(@arguments[:hosts] ||
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
155
|
+
@arguments[:host] ||
|
156
|
+
@arguments[:url] ||
|
157
|
+
@arguments[:urls] ||
|
158
|
+
ENV['ELASTICSEARCH_URL'] ||
|
159
|
+
DEFAULT_HOST)
|
124
160
|
|
125
161
|
@send_get_body_as = @arguments[:send_get_body_as] || 'GET'
|
162
|
+
@opaque_id_prefix = @arguments[:opaque_id_prefix] || nil
|
163
|
+
@ca_fingerprint = @arguments.delete(:ca_fingerprint)
|
126
164
|
|
127
165
|
if @arguments[:request_timeout]
|
128
|
-
@arguments[:transport_options][:request] = { :
|
166
|
+
@arguments[:transport_options][:request] = { timeout: @arguments[:request_timeout] }
|
129
167
|
end
|
130
168
|
|
131
169
|
if @arguments[:transport]
|
132
170
|
@transport = @arguments[:transport]
|
133
171
|
else
|
134
|
-
transport_class
|
135
|
-
if transport_class == Transport::HTTP::Faraday
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
172
|
+
@transport_class = @arguments[:transport_class] || DEFAULT_TRANSPORT_CLASS
|
173
|
+
@transport = if @transport_class == Transport::HTTP::Faraday
|
174
|
+
@arguments[:adapter] ||= __auto_detect_adapter
|
175
|
+
set_meta_header # from include MetaHeader
|
176
|
+
@transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
|
177
|
+
faraday.adapter(@arguments[:adapter])
|
178
|
+
block&.call faraday
|
179
|
+
end
|
180
|
+
else
|
181
|
+
set_meta_header # from include MetaHeader
|
182
|
+
@transport_class.new(hosts: @seeds, options: @arguments)
|
183
|
+
end
|
145
184
|
end
|
146
185
|
end
|
147
186
|
|
148
187
|
# Performs a request through delegation to {#transport}.
|
149
188
|
#
|
150
|
-
def perform_request(method, path, params={}, body=nil, headers=nil)
|
189
|
+
def perform_request(method, path, params = {}, body = nil, headers = nil)
|
151
190
|
method = @send_get_body_as if 'GET' == method && body
|
191
|
+
if (opaque_id = params.delete(:opaque_id))
|
192
|
+
headers = {} if headers.nil?
|
193
|
+
opaque_id = @opaque_id_prefix ? "#{@opaque_id_prefix}#{opaque_id}" : opaque_id
|
194
|
+
headers.merge!('X-Opaque-Id' => opaque_id)
|
195
|
+
end
|
196
|
+
validate_ca_fingerprints if @ca_fingerprint
|
152
197
|
transport.perform_request(method, path, params, body, headers)
|
153
198
|
end
|
154
199
|
|
155
200
|
private
|
156
201
|
|
202
|
+
def set_api_key
|
203
|
+
@api_key = __encode(@api_key) if @api_key.is_a? Hash
|
204
|
+
add_header('Authorization' => "ApiKey #{@api_key}")
|
205
|
+
@arguments.delete(:user)
|
206
|
+
@arguments.delete(:password)
|
207
|
+
end
|
208
|
+
|
209
|
+
def set_compatibility_header
|
210
|
+
return unless ['1', 'true'].include?(ENV['ELASTIC_CLIENT_APIVERSIONING'])
|
211
|
+
return if instance_variable_get('@options').dig(:transport_options, :headers, 'Accept')
|
212
|
+
|
213
|
+
add_header(
|
214
|
+
{
|
215
|
+
'Accept' => 'application/vnd.elasticsearch+json; compatible-with=7',
|
216
|
+
'Content-Type' => 'application/vnd.elasticsearch+json; compatible-with=7'
|
217
|
+
}
|
218
|
+
)
|
219
|
+
end
|
220
|
+
|
221
|
+
def validate_ca_fingerprints
|
222
|
+
transport.connections.connections.each do |connection|
|
223
|
+
unless connection.host[:scheme] == 'https'
|
224
|
+
raise Elasticsearch::Transport::Transport::Error, 'CA fingerprinting can\'t be configured over http'
|
225
|
+
end
|
226
|
+
|
227
|
+
next if connection.verified
|
228
|
+
|
229
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
230
|
+
socket = TCPSocket.new(connection.host[:host], connection.host[:port])
|
231
|
+
ssl = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
232
|
+
ssl.connect
|
233
|
+
cert_store = ssl.peer_cert_chain
|
234
|
+
matching_certs = cert_store.select do |cert|
|
235
|
+
OpenSSL::Digest::SHA256.hexdigest(cert.to_der).upcase == @ca_fingerprint.upcase.gsub(':', '')
|
236
|
+
end
|
237
|
+
if matching_certs.empty?
|
238
|
+
raise Elasticsearch::Transport::Transport::Error,
|
239
|
+
'Server certificate CA fingerprint does not match the value configured in ca_fingerprint'
|
240
|
+
end
|
241
|
+
|
242
|
+
connection.verified = true
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def add_header(header)
|
247
|
+
headers = @arguments[:transport_options]&.[](:headers) || {}
|
248
|
+
headers.merge!(header)
|
249
|
+
@arguments[:transport_options].merge!(
|
250
|
+
headers: headers
|
251
|
+
)
|
252
|
+
end
|
253
|
+
|
157
254
|
def extract_cloud_creds(arguments)
|
158
|
-
return unless arguments[:cloud_id]
|
255
|
+
return unless arguments[:cloud_id] && !arguments[:cloud_id].empty?
|
256
|
+
|
159
257
|
name = arguments[:cloud_id].split(':')[0]
|
160
258
|
cloud_url, elasticsearch_instance = Base64.decode64(arguments[:cloud_id].gsub("#{name}:", '')).split('$')
|
161
|
-
|
259
|
+
|
260
|
+
if cloud_url.include?(':')
|
261
|
+
url, port = cloud_url.split(':')
|
262
|
+
host = "#{elasticsearch_instance}.#{url}"
|
263
|
+
else
|
264
|
+
host = "#{elasticsearch_instance}.#{cloud_url}"
|
265
|
+
port = arguments[:port] || DEFAULT_CLOUD_PORT
|
266
|
+
end
|
267
|
+
[
|
268
|
+
{
|
269
|
+
scheme: 'https',
|
162
270
|
user: arguments[:user],
|
163
271
|
password: arguments[:password],
|
164
|
-
host:
|
165
|
-
port:
|
272
|
+
host: host,
|
273
|
+
port: port.to_i
|
274
|
+
}
|
275
|
+
]
|
166
276
|
end
|
167
277
|
|
168
278
|
# Normalizes and returns hosts configuration.
|
@@ -195,39 +305,47 @@ module Elasticsearch
|
|
195
305
|
|
196
306
|
def __parse_host(host)
|
197
307
|
host_parts = case host
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
308
|
+
when String
|
309
|
+
if host =~ /^[a-z]+\:\/\//
|
310
|
+
# Construct a new `URI::Generic` directly from the array returned by URI::split.
|
311
|
+
# This avoids `URI::HTTP` and `URI::HTTPS`, which supply default ports.
|
312
|
+
uri = URI::Generic.new(*URI.split(host))
|
313
|
+
default_port = uri.scheme == 'https' ? 443 : DEFAULT_PORT
|
314
|
+
{
|
315
|
+
scheme: uri.scheme,
|
316
|
+
user: uri.user,
|
317
|
+
password: uri.password,
|
318
|
+
host: uri.host,
|
319
|
+
path: uri.path,
|
320
|
+
port: uri.port || default_port
|
321
|
+
}
|
322
|
+
else
|
323
|
+
host, port = host.split(':')
|
324
|
+
{ host: host, port: port }
|
325
|
+
end
|
326
|
+
when URI
|
327
|
+
{
|
328
|
+
scheme: host.scheme,
|
329
|
+
user: host.user,
|
330
|
+
password: host.password,
|
331
|
+
host: host.host,
|
332
|
+
path: host.path,
|
333
|
+
port: host.port
|
334
|
+
}
|
335
|
+
when Hash
|
336
|
+
host
|
337
|
+
else
|
338
|
+
raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
|
339
|
+
end
|
340
|
+
if @api_key
|
341
|
+
# Remove Basic Auth if using API KEY
|
342
|
+
host_parts.delete(:user)
|
343
|
+
host_parts.delete(:password)
|
224
344
|
else
|
225
|
-
|
345
|
+
@options[:http][:user] ||= host_parts[:user]
|
346
|
+
@options[:http][:password] ||= host_parts[:password]
|
226
347
|
end
|
227
348
|
|
228
|
-
@options[:http][:user] ||= host_parts[:user]
|
229
|
-
@options[:http][:password] ||= host_parts[:password]
|
230
|
-
|
231
349
|
host_parts[:port] = host_parts[:port].to_i if host_parts[:port]
|
232
350
|
host_parts[:path].chomp!('/') if host_parts[:path]
|
233
351
|
host_parts
|
@@ -255,6 +373,13 @@ module Elasticsearch
|
|
255
373
|
::Faraday.default_adapter
|
256
374
|
end
|
257
375
|
end
|
376
|
+
|
377
|
+
# Encode credentials for the Authorization Header
|
378
|
+
# Credentials is the base64 encoding of id and api_key joined by a colon
|
379
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
|
380
|
+
def __encode(api_key)
|
381
|
+
Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':'))
|
382
|
+
end
|
258
383
|
end
|
259
384
|
end
|
260
385
|
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
require 'base64'
|
19
|
+
|
20
|
+
module Elasticsearch
|
21
|
+
module Transport
|
22
|
+
# Methods for the Elastic meta header used by Cloud.
|
23
|
+
# X-Elastic-Client-Meta HTTP header which is used by Elastic Cloud and can be disabled when
|
24
|
+
# instantiating the Client with the :enable_meta_header parameter set to `false`.
|
25
|
+
#
|
26
|
+
module MetaHeader
|
27
|
+
def set_meta_header
|
28
|
+
return if @arguments[:enable_meta_header] == false
|
29
|
+
|
30
|
+
service, version = meta_header_service_version
|
31
|
+
|
32
|
+
meta_headers = {
|
33
|
+
service.to_sym => version,
|
34
|
+
rb: RUBY_VERSION,
|
35
|
+
t: Elasticsearch::Transport::VERSION
|
36
|
+
}
|
37
|
+
meta_headers.merge!(meta_header_engine) if meta_header_engine
|
38
|
+
meta_headers.merge!(meta_header_adapter) if meta_header_adapter
|
39
|
+
|
40
|
+
add_header({ 'x-elastic-client-meta' => meta_headers.map { |k, v| "#{k}=#{v}" }.join(',') })
|
41
|
+
end
|
42
|
+
|
43
|
+
def meta_header_service_version
|
44
|
+
if enterprise_search?
|
45
|
+
Elastic::ENTERPRISE_SERVICE_VERSION
|
46
|
+
elsif elasticsearch?
|
47
|
+
Elastic::ELASTICSEARCH_SERVICE_VERSION
|
48
|
+
elsif defined?(Elasticsearch::VERSION)
|
49
|
+
[:es, client_meta_version(Elasticsearch::VERSION)]
|
50
|
+
else
|
51
|
+
[:es, client_meta_version(Elasticsearch::Transport::VERSION)]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def enterprise_search?
|
56
|
+
defined?(Elastic::ENTERPRISE_SERVICE_VERSION) &&
|
57
|
+
called_from?('enterprise-search-ruby')
|
58
|
+
end
|
59
|
+
|
60
|
+
def elasticsearch?
|
61
|
+
defined?(Elastic::ELASTICSEARCH_SERVICE_VERSION) &&
|
62
|
+
called_from?('elasticsearch')
|
63
|
+
end
|
64
|
+
|
65
|
+
def called_from?(service)
|
66
|
+
!caller.select { |c| c.match?(service) }.empty?
|
67
|
+
end
|
68
|
+
|
69
|
+
# We return the current version if it's a release, but if it's a pre/alpha/beta release we
|
70
|
+
# return <VERSION_NUMBER>p
|
71
|
+
#
|
72
|
+
def client_meta_version(version)
|
73
|
+
regexp = /^([0-9]+\.[0-9]+\.[0-9]+)(\.?[a-z0-9.-]+)?$/
|
74
|
+
match = version.match(regexp)
|
75
|
+
return "#{match[1]}p" if (match[2])
|
76
|
+
|
77
|
+
version
|
78
|
+
end
|
79
|
+
|
80
|
+
def meta_header_engine
|
81
|
+
case RUBY_ENGINE
|
82
|
+
when 'ruby'
|
83
|
+
{}
|
84
|
+
when 'jruby'
|
85
|
+
{ jv: ENV_JAVA['java.version'], jr: JRUBY_VERSION }
|
86
|
+
when 'rbx'
|
87
|
+
{ rbx: RUBY_VERSION }
|
88
|
+
else
|
89
|
+
{ RUBY_ENGINE.to_sym => RUBY_VERSION }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# This function tries to define the version for the Faraday adapter. If it hasn't been loaded
|
94
|
+
# by the time we're calling this method, it's going to report the adapter (if we know it) but
|
95
|
+
# return 0 as the version. It won't report anything when using a custom adapter we don't
|
96
|
+
# identify.
|
97
|
+
#
|
98
|
+
# Returns a Hash<adapter_alias, version>
|
99
|
+
#
|
100
|
+
def meta_header_adapter
|
101
|
+
if @transport_class == Transport::HTTP::Faraday
|
102
|
+
version = '0'
|
103
|
+
adapter_version = case @arguments[:adapter]
|
104
|
+
when :patron
|
105
|
+
version = Patron::VERSION if defined?(::Patron::VERSION)
|
106
|
+
{pt: version}
|
107
|
+
when :net_http
|
108
|
+
version = if defined?(Net::HTTP::VERSION)
|
109
|
+
Net::HTTP::VERSION
|
110
|
+
elsif defined?(Net::HTTP::HTTPVersion)
|
111
|
+
Net::HTTP::HTTPVersion
|
112
|
+
end
|
113
|
+
{nh: version}
|
114
|
+
when :typhoeus
|
115
|
+
version = Typhoeus::VERSION if defined?(::Typhoeus::VERSION)
|
116
|
+
{ty: version}
|
117
|
+
when :httpclient
|
118
|
+
version = HTTPClient::VERSION if defined?(HTTPClient::VERSION)
|
119
|
+
{hc: version}
|
120
|
+
when :net_http_persistent
|
121
|
+
version = Net::HTTP::Persistent::VERSION if defined?(Net::HTTP::Persistent::VERSION)
|
122
|
+
{np: version}
|
123
|
+
else
|
124
|
+
{}
|
125
|
+
end
|
126
|
+
{fd: Faraday::VERSION}.merge(adapter_version)
|
127
|
+
elsif defined?(Transport::HTTP::Curb) && @transport_class == Transport::HTTP::Curb
|
128
|
+
{cl: Curl::CURB_VERSION}
|
129
|
+
elsif defined?(Transport::HTTP::Manticore) && @transport_class == Transport::HTTP::Manticore
|
130
|
+
{mc: Manticore::VERSION}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -1,6 +1,19 @@
|
|
1
|
-
# Licensed to Elasticsearch B.V under one or more
|
2
|
-
#
|
3
|
-
#
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
4
17
|
|
5
18
|
module Elasticsearch
|
6
19
|
module Transport
|