elasticsearch-transport 7.5.0 → 7.13.3
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 +28 -11
- data/README.md +158 -58
- data/Rakefile +16 -3
- data/elasticsearch-transport.gemspec +57 -63
- data/lib/elasticsearch/transport/client.rb +150 -56
- data/lib/elasticsearch/transport/meta_header.rb +135 -0
- data/lib/elasticsearch/transport/redacted.rb +16 -3
- data/lib/elasticsearch/transport/transport/base.rb +32 -12
- data/lib/elasticsearch/transport/transport/connections/collection.rb +18 -8
- data/lib/elasticsearch/transport/transport/connections/connection.rb +23 -8
- data/lib/elasticsearch/transport/transport/connections/selector.rb +16 -3
- data/lib/elasticsearch/transport/transport/errors.rb +16 -3
- data/lib/elasticsearch/transport/transport/http/curb.rb +16 -3
- data/lib/elasticsearch/transport/transport/http/faraday.rb +27 -6
- data/lib/elasticsearch/transport/transport/http/manticore.rb +16 -3
- data/lib/elasticsearch/transport/transport/loggable.rb +16 -3
- data/lib/elasticsearch/transport/transport/response.rb +16 -4
- 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 +16 -3
- 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 +60 -38
- data/spec/elasticsearch/transport/client_spec.rb +628 -132
- data/spec/elasticsearch/transport/meta_header_spec.rb +265 -0
- data/spec/elasticsearch/transport/sniffer_spec.rb +16 -16
- data/spec/spec_helper.rb +19 -1
- data/test/integration/transport_test.rb +30 -4
- data/test/profile/client_benchmark_test.rb +16 -3
- data/test/test_helper.rb +16 -3
- data/test/unit/connection_test.rb +23 -5
- data/test/unit/response_test.rb +17 -4
- data/test/unit/serializer_test.rb +16 -3
- data/test/unit/transport_base_test.rb +17 -4
- data/test/unit/transport_curb_test.rb +16 -3
- data/test/unit/transport_faraday_test.rb +18 -5
- data/test/unit/transport_manticore_test.rb +29 -16
- metadata +70 -69
@@ -1,8 +1,22 @@
|
|
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
|
@@ -12,6 +26,7 @@ module Elasticsearch
|
|
12
26
|
# See {file:README.md README} for usage and code examples.
|
13
27
|
#
|
14
28
|
class Client
|
29
|
+
include MetaHeader
|
15
30
|
DEFAULT_TRANSPORT_CLASS = Transport::HTTP::Faraday
|
16
31
|
|
17
32
|
DEFAULT_LOGGER = lambda do
|
@@ -36,9 +51,15 @@ module Elasticsearch
|
|
36
51
|
DEFAULT_HOST = 'localhost:9200'.freeze
|
37
52
|
|
38
53
|
# The default port to use if connecting using a Cloud ID.
|
54
|
+
# Updated from 9243 to 443 in client version 7.10.1
|
39
55
|
#
|
40
56
|
# @since 7.2.0
|
41
|
-
DEFAULT_CLOUD_PORT =
|
57
|
+
DEFAULT_CLOUD_PORT = 443
|
58
|
+
|
59
|
+
# The default port to use if not otherwise specified.
|
60
|
+
#
|
61
|
+
# @since 7.2.0
|
62
|
+
DEFAULT_PORT = 9200
|
42
63
|
|
43
64
|
# Returns the transport object.
|
44
65
|
#
|
@@ -99,6 +120,14 @@ module Elasticsearch
|
|
99
120
|
# The default is false. Responses will automatically be inflated if they are compressed.
|
100
121
|
# If a custom transport object is used, it must handle the request compression and response inflation.
|
101
122
|
#
|
123
|
+
# @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key`
|
124
|
+
# joined by a colon as a String, or a hash with the `id` and `api_key` values.
|
125
|
+
# @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client.
|
126
|
+
# This will be prepended to the id you set before each request
|
127
|
+
# if you're using X-Opaque-Id
|
128
|
+
# @option enable_meta_header [Boolean] :enable_meta_header Enable sending the meta data header to Cloud.
|
129
|
+
# (Default: true)
|
130
|
+
#
|
102
131
|
# @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block
|
103
132
|
#
|
104
133
|
def initialize(arguments={}, &block)
|
@@ -112,57 +141,107 @@ module Elasticsearch
|
|
112
141
|
@arguments[:randomize_hosts] ||= false
|
113
142
|
@arguments[:transport_options] ||= {}
|
114
143
|
@arguments[:http] ||= {}
|
144
|
+
@arguments[:enable_meta_header] = arguments.fetch(:enable_meta_header) { true }
|
115
145
|
@options[:http] ||= {}
|
116
146
|
|
147
|
+
set_api_key if (@api_key = @arguments[:api_key])
|
148
|
+
set_compatibility_header if ENV['ELASTIC_CLIENT_APIVERSIONING']
|
149
|
+
|
117
150
|
@seeds = extract_cloud_creds(@arguments)
|
118
151
|
@seeds ||= __extract_hosts(@arguments[:hosts] ||
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
152
|
+
@arguments[:host] ||
|
153
|
+
@arguments[:url] ||
|
154
|
+
@arguments[:urls] ||
|
155
|
+
ENV['ELASTICSEARCH_URL'] ||
|
156
|
+
DEFAULT_HOST)
|
124
157
|
|
125
158
|
@send_get_body_as = @arguments[:send_get_body_as] || 'GET'
|
159
|
+
@opaque_id_prefix = @arguments[:opaque_id_prefix] || nil
|
126
160
|
|
127
161
|
if @arguments[:request_timeout]
|
128
|
-
@arguments[:transport_options][:request] = { :
|
162
|
+
@arguments[:transport_options][:request] = { timeout: @arguments[:request_timeout] }
|
129
163
|
end
|
130
164
|
|
131
165
|
if @arguments[:transport]
|
132
166
|
@transport = @arguments[:transport]
|
133
167
|
else
|
134
|
-
transport_class
|
135
|
-
if transport_class == Transport::HTTP::Faraday
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
168
|
+
@transport_class = @arguments[:transport_class] || DEFAULT_TRANSPORT_CLASS
|
169
|
+
@transport = if @transport_class == Transport::HTTP::Faraday
|
170
|
+
@arguments[:adapter] ||= __auto_detect_adapter
|
171
|
+
set_meta_header # from include MetaHeader
|
172
|
+
@transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
|
173
|
+
faraday.adapter(@arguments[:adapter])
|
174
|
+
block&.call faraday
|
175
|
+
end
|
176
|
+
else
|
177
|
+
set_meta_header # from include MetaHeader
|
178
|
+
@transport_class.new(hosts: @seeds, options: @arguments)
|
179
|
+
end
|
145
180
|
end
|
146
181
|
end
|
147
182
|
|
148
183
|
# Performs a request through delegation to {#transport}.
|
149
184
|
#
|
150
|
-
def perform_request(method, path, params={}, body=nil, headers=nil)
|
185
|
+
def perform_request(method, path, params = {}, body = nil, headers = nil)
|
151
186
|
method = @send_get_body_as if 'GET' == method && body
|
187
|
+
if (opaque_id = params.delete(:opaque_id))
|
188
|
+
headers = {} if headers.nil?
|
189
|
+
opaque_id = @opaque_id_prefix ? "#{@opaque_id_prefix}#{opaque_id}" : opaque_id
|
190
|
+
headers.merge!('X-Opaque-Id' => opaque_id)
|
191
|
+
end
|
152
192
|
transport.perform_request(method, path, params, body, headers)
|
153
193
|
end
|
154
194
|
|
155
195
|
private
|
156
196
|
|
197
|
+
def set_api_key
|
198
|
+
@api_key = __encode(@api_key) if @api_key.is_a? Hash
|
199
|
+
add_header('Authorization' => "ApiKey #{@api_key}")
|
200
|
+
@arguments.delete(:user)
|
201
|
+
@arguments.delete(:password)
|
202
|
+
end
|
203
|
+
|
204
|
+
def set_compatibility_header
|
205
|
+
return unless ['1', 'true'].include?(ENV['ELASTIC_CLIENT_APIVERSIONING'])
|
206
|
+
|
207
|
+
add_header(
|
208
|
+
{
|
209
|
+
'Accept' => 'application/vnd.elasticsearch+json;compatible-with=7',
|
210
|
+
'Content-Type' => 'application/vnd.elasticsearch+json; compatible-with=7'
|
211
|
+
}
|
212
|
+
)
|
213
|
+
end
|
214
|
+
|
215
|
+
def add_header(header)
|
216
|
+
headers = @arguments[:transport_options]&.[](:headers) || {}
|
217
|
+
headers.merge!(header)
|
218
|
+
@arguments[:transport_options].merge!(
|
219
|
+
headers: headers
|
220
|
+
)
|
221
|
+
end
|
222
|
+
|
157
223
|
def extract_cloud_creds(arguments)
|
158
|
-
return unless arguments[:cloud_id]
|
224
|
+
return unless arguments[:cloud_id] && !arguments[:cloud_id].empty?
|
225
|
+
|
159
226
|
name = arguments[:cloud_id].split(':')[0]
|
160
227
|
cloud_url, elasticsearch_instance = Base64.decode64(arguments[:cloud_id].gsub("#{name}:", '')).split('$')
|
161
|
-
|
228
|
+
|
229
|
+
if cloud_url.include?(':')
|
230
|
+
url, port = cloud_url.split(':')
|
231
|
+
host = "#{elasticsearch_instance}.#{url}"
|
232
|
+
else
|
233
|
+
host = "#{elasticsearch_instance}.#{cloud_url}"
|
234
|
+
port = arguments[:port] || DEFAULT_CLOUD_PORT
|
235
|
+
end
|
236
|
+
[
|
237
|
+
{
|
238
|
+
scheme: 'https',
|
162
239
|
user: arguments[:user],
|
163
240
|
password: arguments[:password],
|
164
|
-
host:
|
165
|
-
port:
|
241
|
+
host: host,
|
242
|
+
port: port.to_i
|
243
|
+
}
|
244
|
+
]
|
166
245
|
end
|
167
246
|
|
168
247
|
# Normalizes and returns hosts configuration.
|
@@ -195,39 +274,47 @@ module Elasticsearch
|
|
195
274
|
|
196
275
|
def __parse_host(host)
|
197
276
|
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
|
-
|
277
|
+
when String
|
278
|
+
if host =~ /^[a-z]+\:\/\//
|
279
|
+
# Construct a new `URI::Generic` directly from the array returned by URI::split.
|
280
|
+
# This avoids `URI::HTTP` and `URI::HTTPS`, which supply default ports.
|
281
|
+
uri = URI::Generic.new(*URI.split(host))
|
282
|
+
default_port = uri.scheme == 'https' ? 443 : DEFAULT_PORT
|
283
|
+
{
|
284
|
+
scheme: uri.scheme,
|
285
|
+
user: uri.user,
|
286
|
+
password: uri.password,
|
287
|
+
host: uri.host,
|
288
|
+
path: uri.path,
|
289
|
+
port: uri.port || default_port
|
290
|
+
}
|
291
|
+
else
|
292
|
+
host, port = host.split(':')
|
293
|
+
{ host: host, port: port }
|
294
|
+
end
|
295
|
+
when URI
|
296
|
+
{
|
297
|
+
scheme: host.scheme,
|
298
|
+
user: host.user,
|
299
|
+
password: host.password,
|
300
|
+
host: host.host,
|
301
|
+
path: host.path,
|
302
|
+
port: host.port
|
303
|
+
}
|
304
|
+
when Hash
|
305
|
+
host
|
306
|
+
else
|
307
|
+
raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
|
308
|
+
end
|
309
|
+
if @api_key
|
310
|
+
# Remove Basic Auth if using API KEY
|
311
|
+
host_parts.delete(:user)
|
312
|
+
host_parts.delete(:password)
|
224
313
|
else
|
225
|
-
|
314
|
+
@options[:http][:user] ||= host_parts[:user]
|
315
|
+
@options[:http][:password] ||= host_parts[:password]
|
226
316
|
end
|
227
317
|
|
228
|
-
@options[:http][:user] ||= host_parts[:user]
|
229
|
-
@options[:http][:password] ||= host_parts[:password]
|
230
|
-
|
231
318
|
host_parts[:port] = host_parts[:port].to_i if host_parts[:port]
|
232
319
|
host_parts[:path].chomp!('/') if host_parts[:path]
|
233
320
|
host_parts
|
@@ -255,6 +342,13 @@ module Elasticsearch
|
|
255
342
|
::Faraday.default_adapter
|
256
343
|
end
|
257
344
|
end
|
345
|
+
|
346
|
+
# Encode credentials for the Authorization Header
|
347
|
+
# Credentials is the base64 encoding of id and api_key joined by a colon
|
348
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
|
349
|
+
def __encode(api_key)
|
350
|
+
Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':'))
|
351
|
+
end
|
258
352
|
end
|
259
353
|
end
|
260
354
|
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
|
@@ -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
|
@@ -34,7 +47,7 @@ module Elasticsearch
|
|
34
47
|
#
|
35
48
|
# @see Client#initialize
|
36
49
|
#
|
37
|
-
def initialize(arguments={}, &block)
|
50
|
+
def initialize(arguments = {}, &block)
|
38
51
|
@state_mutex = Mutex.new
|
39
52
|
|
40
53
|
@hosts = arguments[:hosts] || []
|
@@ -221,9 +234,9 @@ module Elasticsearch
|
|
221
234
|
def __full_url(host)
|
222
235
|
url = "#{host[:protocol]}://"
|
223
236
|
url += "#{CGI.escape(host[:user])}:#{CGI.escape(host[:password])}@" if host[:user]
|
224
|
-
url +=
|
237
|
+
url += host[:host]
|
225
238
|
url += ":#{host[:port]}" if host[:port]
|
226
|
-
url +=
|
239
|
+
url += host[:path] if host[:path]
|
227
240
|
url
|
228
241
|
end
|
229
242
|
|
@@ -245,8 +258,9 @@ module Elasticsearch
|
|
245
258
|
# @raise [ServerError] If request failed on server
|
246
259
|
# @raise [Error] If no connection is available
|
247
260
|
#
|
248
|
-
def perform_request(method, path, params={}, body=nil, headers=nil, opts={}, &block)
|
249
|
-
raise NoMethodError,
|
261
|
+
def perform_request(method, path, params = {}, body = nil, headers = nil, opts = {}, &block)
|
262
|
+
raise NoMethodError, 'Implement this method in your transport class' unless block_given?
|
263
|
+
|
250
264
|
start = Time.now
|
251
265
|
tries = 0
|
252
266
|
reload_on_failure = opts.fetch(:reload_on_failure, @options[:reload_on_failure])
|
@@ -263,15 +277,15 @@ module Elasticsearch
|
|
263
277
|
|
264
278
|
begin
|
265
279
|
tries += 1
|
266
|
-
connection = get_connection or raise Error.new(
|
280
|
+
connection = get_connection or raise Error.new('Cannot get new connection from pool.')
|
267
281
|
|
268
282
|
if connection.connection.respond_to?(:params) && connection.connection.params.respond_to?(:to_hash)
|
269
283
|
params = connection.connection.params.merge(params.to_hash)
|
270
284
|
end
|
271
285
|
|
272
|
-
url
|
286
|
+
url = connection.full_url(path, params)
|
273
287
|
|
274
|
-
response
|
288
|
+
response = block.call(connection, url)
|
275
289
|
|
276
290
|
connection.healthy! if connection.failures > 0
|
277
291
|
|
@@ -342,6 +356,8 @@ module Elasticsearch
|
|
342
356
|
|
343
357
|
__trace method, path, params, connection.connection.headers, body, url, response, nil, 'N/A', duration if tracer
|
344
358
|
|
359
|
+
warnings(response.headers['warning']) if response.headers&.[]('warning')
|
360
|
+
|
345
361
|
Response.new response.status, json || response.body, response.headers
|
346
362
|
ensure
|
347
363
|
@last_request_at = Time.now
|
@@ -415,7 +431,11 @@ module Elasticsearch
|
|
415
431
|
"elasticsearch-ruby/#{VERSION} (#{meta.join('; ')})"
|
416
432
|
end
|
417
433
|
end
|
434
|
+
|
435
|
+
def warnings(warning)
|
436
|
+
warn("warning: #{warning}")
|
437
|
+
end
|
418
438
|
end
|
419
439
|
end
|
420
440
|
end
|
421
|
-
end
|
441
|
+
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
|
@@ -65,16 +78,13 @@ module Elasticsearch
|
|
65
78
|
|
66
79
|
# Returns a connection.
|
67
80
|
#
|
68
|
-
# If there are no alive connections,
|
81
|
+
# If there are no alive connections, returns a connection with least failures.
|
69
82
|
# Delegates to selector's `#select` method to get the connection.
|
70
83
|
#
|
71
84
|
# @return [Connection]
|
72
85
|
#
|
73
86
|
def get_connection(options={})
|
74
|
-
|
75
|
-
dead_connection.alive!
|
76
|
-
end
|
77
|
-
selector.select(options)
|
87
|
+
selector.select(options) || @connections.min_by(&:failures)
|
78
88
|
end
|
79
89
|
|
80
90
|
def each(&block)
|
@@ -1,12 +1,24 @@
|
|
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
|
7
20
|
module Transport
|
8
21
|
module Connections
|
9
|
-
|
10
22
|
# Wraps the connection information and logic.
|
11
23
|
#
|
12
24
|
# The Connection instance wraps the host information (hostname, port, attributes, etc),
|
@@ -41,12 +53,14 @@ module Elasticsearch
|
|
41
53
|
#
|
42
54
|
# @return [String]
|
43
55
|
#
|
44
|
-
def full_url(path, params={})
|
56
|
+
def full_url(path, params = {})
|
45
57
|
url = "#{host[:protocol]}://"
|
46
58
|
url += "#{CGI.escape(host[:user])}:#{CGI.escape(host[:password])}@" if host[:user]
|
47
59
|
url += "#{host[:host]}:#{host[:port]}"
|
48
60
|
url += "#{host[:path]}" if host[:path]
|
49
|
-
|
61
|
+
full_path = full_path(path, params)
|
62
|
+
url += '/' unless full_path.match?(/^\//)
|
63
|
+
url += full_path
|
50
64
|
end
|
51
65
|
|
52
66
|
# Returns the complete endpoint path with serialized parameters.
|
@@ -122,14 +136,15 @@ module Elasticsearch
|
|
122
136
|
}
|
123
137
|
end
|
124
138
|
|
125
|
-
# Equality operator based on connection protocol, host and
|
139
|
+
# Equality operator based on connection protocol, host, port and attributes
|
126
140
|
#
|
127
141
|
# @return [Boolean]
|
128
142
|
#
|
129
143
|
def ==(other)
|
130
144
|
self.host[:protocol] == other.host[:protocol] && \
|
131
145
|
self.host[:host] == other.host[:host] && \
|
132
|
-
self.host[:port].to_i == other.host[:port].to_i
|
146
|
+
self.host[:port].to_i == other.host[:port].to_i && \
|
147
|
+
self.host[:attributes] == other.host[:attributes]
|
133
148
|
end
|
134
149
|
|
135
150
|
# @return [String]
|
@@ -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
|