elastic-transport 8.1.3 → 8.2.0
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/.github/workflows/license.yml +1 -1
- data/.github/workflows/tests.yml +48 -8
- data/.gitignore +1 -1
- data/CHANGELOG.md +6 -17
- data/Gemfile +4 -8
- data/Gemfile-faraday1.gemfile +39 -0
- data/README.md +1 -1
- data/Rakefile +48 -1
- data/elastic-transport.gemspec +5 -8
- data/lib/elastic/transport/client.rb +13 -10
- data/lib/elastic/transport/meta_header.rb +10 -8
- data/lib/elastic/transport/transport/base.rb +53 -50
- data/lib/elastic/transport/transport/errors.rb +2 -4
- data/lib/elastic/transport/transport/http/curb.rb +28 -25
- data/lib/elastic/transport/transport/http/faraday.rb +29 -27
- data/lib/elastic/transport/transport/http/manticore.rb +1 -1
- data/lib/elastic/transport/transport/response.rb +3 -2
- data/lib/elastic/transport/transport/sniffer.rb +1 -3
- data/lib/elastic/transport/version.rb +1 -1
- data/spec/elastic/transport/base_spec.rb +4 -2
- data/spec/elastic/transport/client_spec.rb +13 -16
- data/spec/elastic/transport/meta_header_spec.rb +2 -2
- data/spec/elastic/transport/sniffer_spec.rb +0 -18
- data/spec/spec_helper.rb +4 -1
- data/test/integration/jruby_test.rb +1 -1
- data/test/integration/transport_test.rb +86 -40
- data/test/test_helper.rb +8 -5
- data/test/unit/adapters_test.rb +88 -0
- data/test/unit/transport_curb_test.rb +2 -3
- metadata +17 -70
@@ -24,12 +24,12 @@ module Elastic
|
|
24
24
|
include Loggable
|
25
25
|
|
26
26
|
DEFAULT_PORT = 9200
|
27
|
-
DEFAULT_PROTOCOL = 'http'
|
27
|
+
DEFAULT_PROTOCOL = 'http'.freeze
|
28
28
|
DEFAULT_RELOAD_AFTER = 10_000 # Requests
|
29
29
|
DEFAULT_RESURRECT_AFTER = 60 # Seconds
|
30
30
|
DEFAULT_MAX_RETRIES = 3 # Requests
|
31
31
|
DEFAULT_SERIALIZER_CLASS = Serializer::MultiJson
|
32
|
-
SANITIZED_PASSWORD = '*' * (rand(14)+1)
|
32
|
+
SANITIZED_PASSWORD = '*' * (rand(14) + 1)
|
33
33
|
|
34
34
|
attr_reader :hosts, :options, :connections, :counter, :last_request_at, :protocol
|
35
35
|
attr_accessor :serializer, :sniffer, :logger, :tracer,
|
@@ -59,7 +59,7 @@ module Elastic
|
|
59
59
|
@compression = !!@options[:compression]
|
60
60
|
@connections = __build_connections
|
61
61
|
|
62
|
-
@serializer = options[:serializer] || ( options[:serializer_class] ? options[:serializer_class].new(self) : DEFAULT_SERIALIZER_CLASS.new(self)
|
62
|
+
@serializer = options[:serializer] || ( options[:serializer_class] ? options[:serializer_class].new(self) : DEFAULT_SERIALIZER_CLASS.new(self))
|
63
63
|
@protocol = options[:protocol] || DEFAULT_PROTOCOL
|
64
64
|
|
65
65
|
@logger = options[:logger]
|
@@ -72,7 +72,7 @@ module Elastic
|
|
72
72
|
@reload_connections = options[:reload_connections]
|
73
73
|
@reload_after = options[:reload_connections].is_a?(Integer) ? options[:reload_connections] : DEFAULT_RELOAD_AFTER
|
74
74
|
@resurrect_after = options[:resurrect_after] || DEFAULT_RESURRECT_AFTER
|
75
|
-
@retry_on_status = Array(options[:retry_on_status]).map
|
75
|
+
@retry_on_status = Array(options[:retry_on_status]).map(&:to_i)
|
76
76
|
end
|
77
77
|
|
78
78
|
# Returns a connection from the connection pool by delegating to {Connections::Collection#get_connection}.
|
@@ -87,7 +87,7 @@ module Elastic
|
|
87
87
|
resurrect_dead_connections! if Time.now > @last_request_at + @resurrect_after
|
88
88
|
|
89
89
|
@counter_mtx.synchronize { @counter += 1 }
|
90
|
-
reload_connections!
|
90
|
+
reload_connections! if reload_connections && (counter % reload_after).zero?
|
91
91
|
connections.get_connection(options)
|
92
92
|
end
|
93
93
|
|
@@ -97,10 +97,10 @@ module Elastic
|
|
97
97
|
#
|
98
98
|
def reload_connections!
|
99
99
|
hosts = sniffer.hosts
|
100
|
-
__rebuild_connections
|
100
|
+
__rebuild_connections(hosts: hosts, options: options)
|
101
101
|
self
|
102
102
|
rescue SnifferTimeoutError
|
103
|
-
log_error
|
103
|
+
log_error('[SnifferTimeoutError] Timeout when reloading connections.')
|
104
104
|
self
|
105
105
|
end
|
106
106
|
|
@@ -109,7 +109,7 @@ module Elastic
|
|
109
109
|
# @see Connections::Connection#resurrect!
|
110
110
|
#
|
111
111
|
def resurrect_dead_connections!
|
112
|
-
connections.dead.each
|
112
|
+
connections.dead.each(&:resurrect!)
|
113
113
|
end
|
114
114
|
|
115
115
|
# Rebuilds the connections collection in the transport.
|
@@ -128,7 +128,7 @@ module Elastic
|
|
128
128
|
__close_connections
|
129
129
|
|
130
130
|
new_connections = __build_connections
|
131
|
-
stale_connections = @connections.all.
|
131
|
+
stale_connections = @connections.all.reject { |c| new_connections.include?(c) }
|
132
132
|
new_connections = new_connections.reject { |c| @connections.all.include?(c) }
|
133
133
|
|
134
134
|
@connections.remove(stale_connections)
|
@@ -177,8 +177,8 @@ module Elastic
|
|
177
177
|
# @return [Connections::Connection]
|
178
178
|
# @api private
|
179
179
|
#
|
180
|
-
def __build_connection(host, options={}, block=nil)
|
181
|
-
raise NoMethodError,
|
180
|
+
def __build_connection(host, options = {}, block = nil)
|
181
|
+
raise NoMethodError, 'Implement this method in your class'
|
182
182
|
end
|
183
183
|
|
184
184
|
# Closes the connections collection
|
@@ -209,14 +209,14 @@ module Elastic
|
|
209
209
|
#
|
210
210
|
def __trace(method, path, params, headers, body, url, response, json, took, duration)
|
211
211
|
trace_url = "http://localhost:9200/#{path}?pretty" +
|
212
|
-
(
|
212
|
+
(params.empty? ? '' : "&#{::Faraday::Utils::ParamsHash[params].to_query}")
|
213
213
|
trace_body = body ? " -d '#{__convert_to_json(body, :pretty => true)}'" : ''
|
214
214
|
trace_command = "curl -X #{method.to_s.upcase}"
|
215
|
-
trace_command += " -H '#{headers.collect { |k,v| "#{k}: #{v}" }.join(", ")}'" if headers && !headers.empty?
|
215
|
+
trace_command += " -H '#{headers.collect { |k, v| "#{k}: #{v}" }.join(", ")}'" if headers && !headers.empty?
|
216
216
|
trace_command += " '#{trace_url}'#{trace_body}\n"
|
217
217
|
tracer.info trace_command
|
218
218
|
tracer.debug "# #{Time.now.iso8601} [#{response.status}] (#{format('%.3f', duration)}s)\n#"
|
219
|
-
tracer.debug json ? serializer.dump(json, :
|
219
|
+
tracer.debug json ? serializer.dump(json, pretty: true).gsub(/^/, '# ').sub(/\}$/, "\n# }")+"\n" : "# #{response.body}\n"
|
220
220
|
end
|
221
221
|
|
222
222
|
# Raise error specific for the HTTP response status or a generic server error
|
@@ -276,40 +276,37 @@ module Elastic
|
|
276
276
|
reload_on_failure = opts.fetch(:reload_on_failure, @options[:reload_on_failure])
|
277
277
|
delay_on_retry = opts.fetch(:delay_on_retry, @options[:delay_on_retry])
|
278
278
|
|
279
|
-
max_retries =
|
280
|
-
opts[:retry_on_failure] === true ? DEFAULT_MAX_RETRIES : opts[:retry_on_failure]
|
281
|
-
elsif options.key?(:retry_on_failure)
|
282
|
-
options[:retry_on_failure] === true ? DEFAULT_MAX_RETRIES : options[:retry_on_failure]
|
283
|
-
end
|
279
|
+
max_retries = max_retries(opts) || max_retries(options)
|
284
280
|
|
285
281
|
params = params.clone
|
286
|
-
|
282
|
+
# Transforms ignore status codes to Integer
|
283
|
+
ignore = Array(params.delete(:ignore)).compact.map(&:to_i)
|
287
284
|
|
288
285
|
begin
|
289
286
|
sleep(delay_on_retry / 1000.0) if tries > 0
|
290
|
-
tries
|
287
|
+
tries += 1
|
291
288
|
connection = get_connection or raise Error.new('Cannot get new connection from pool.')
|
292
289
|
|
293
|
-
if connection.connection.respond_to?(:params) &&
|
290
|
+
if connection.connection.respond_to?(:params) &&
|
291
|
+
connection.connection.params.respond_to?(:to_hash)
|
294
292
|
params = connection.connection.params.merge(params.to_hash)
|
295
293
|
end
|
296
294
|
|
297
|
-
url
|
295
|
+
url = connection.full_url(path, params)
|
298
296
|
response = block.call(connection, url)
|
299
|
-
connection.healthy! if connection.failures
|
297
|
+
connection.healthy! if connection.failures.positive?
|
300
298
|
|
301
299
|
# Raise an exception so we can catch it for `retry_on_status`
|
302
|
-
__raise_transport_error(response) if response.status.to_i >= 300 &&
|
300
|
+
__raise_transport_error(response) if response.status.to_i >= 300 &&
|
301
|
+
@retry_on_status.include?(response.status.to_i)
|
303
302
|
rescue Elastic::Transport::Transport::ServerError => e
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
log_fatal "[#{e.class}] Cannot get response from #{url} after #{tries} tries"
|
310
|
-
raise e
|
311
|
-
end
|
303
|
+
raise e unless response && @retry_on_status.include?(response.status)
|
304
|
+
|
305
|
+
log_warn "[#{e.class}] Attempt #{tries} to get response from #{url}"
|
306
|
+
if tries <= (max_retries || DEFAULT_MAX_RETRIES)
|
307
|
+
retry
|
312
308
|
else
|
309
|
+
log_fatal "[#{e.class}] Cannot get response from #{url} after #{tries} tries"
|
313
310
|
raise e
|
314
311
|
end
|
315
312
|
rescue *host_unreachable_exceptions => e
|
@@ -317,22 +314,20 @@ module Elastic
|
|
317
314
|
|
318
315
|
connection.dead!
|
319
316
|
|
320
|
-
if reload_on_failure
|
317
|
+
if reload_on_failure && tries < connections.all.size
|
321
318
|
log_warn "[#{e.class}] Reloading connections (attempt #{tries} of #{connections.all.size})"
|
322
319
|
reload_connections! and retry
|
323
320
|
end
|
324
321
|
|
325
322
|
exception = Elastic::Transport::Transport::Error.new(e.message)
|
326
323
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
log_fatal "[#{e.class}] Cannot connect to #{connection.host.inspect} after #{tries} tries"
|
333
|
-
raise exception
|
334
|
-
end
|
324
|
+
raise exception unless max_retries
|
325
|
+
|
326
|
+
log_warn "[#{e.class}] Attempt #{tries} connecting to #{connection.host.inspect}"
|
327
|
+
if tries <= max_retries
|
328
|
+
retry
|
335
329
|
else
|
330
|
+
log_fatal "[#{e.class}] Cannot connect to #{connection.host.inspect} after #{tries} tries"
|
336
331
|
raise exception
|
337
332
|
end
|
338
333
|
rescue Exception => e
|
@@ -351,8 +346,11 @@ module Elastic
|
|
351
346
|
__raise_transport_error response unless ignore.include?(response.status.to_i)
|
352
347
|
end
|
353
348
|
|
354
|
-
json
|
355
|
-
|
349
|
+
json = serializer.load(response.body) if response.body &&
|
350
|
+
!response.body.empty? &&
|
351
|
+
response.headers &&
|
352
|
+
response.headers["content-type"] =~ /json/
|
353
|
+
took = (json['took'] ? sprintf('%.3fs', json['took'] / 1000.0) : 'n/a') rescue 'n/a'
|
356
354
|
__log_response(method, path, params, body, url, response, json, took, duration) unless ignore.include?(response.status.to_i)
|
357
355
|
__trace(method, path, params, connection_headers(connection), body, url, response, nil, 'N/A', duration) if tracer
|
358
356
|
log_warn(response.headers['warning']) if response.headers&.[]('warning')
|
@@ -374,17 +372,21 @@ module Elastic
|
|
374
372
|
private
|
375
373
|
|
376
374
|
USER_AGENT_STR = 'User-Agent'.freeze
|
377
|
-
USER_AGENT_REGEX = /user
|
375
|
+
USER_AGENT_REGEX = /user-?_?agent/
|
378
376
|
ACCEPT_ENCODING = 'Accept-Encoding'.freeze
|
379
377
|
CONTENT_ENCODING = 'Content-Encoding'.freeze
|
380
378
|
CONTENT_TYPE_STR = 'Content-Type'.freeze
|
381
|
-
CONTENT_TYPE_REGEX = /content
|
379
|
+
CONTENT_TYPE_REGEX = /content-?_?type/
|
382
380
|
DEFAULT_CONTENT_TYPE = 'application/json'.freeze
|
383
381
|
GZIP = 'gzip'.freeze
|
384
382
|
GZIP_FIRST_TWO_BYTES = '1f8b'.freeze
|
385
383
|
HEX_STRING_DIRECTIVE = 'H*'.freeze
|
386
384
|
RUBY_ENCODING = '1.9'.respond_to?(:force_encoding)
|
387
385
|
|
386
|
+
def max_retries(opts)
|
387
|
+
opts[:retry_on_failure] == true ? DEFAULT_MAX_RETRIES : opts[:retry_on_failure]
|
388
|
+
end
|
389
|
+
|
388
390
|
def compress_request(body, headers)
|
389
391
|
if body
|
390
392
|
headers ||= {}
|
@@ -411,7 +413,7 @@ module Elastic
|
|
411
413
|
|
412
414
|
io = StringIO.new(body)
|
413
415
|
gzip_reader = if RUBY_ENCODING
|
414
|
-
Zlib::GzipReader.new(io, :
|
416
|
+
Zlib::GzipReader.new(io, encoding: 'ASCII-8BIT')
|
415
417
|
else
|
416
418
|
Zlib::GzipReader.new(io)
|
417
419
|
end
|
@@ -429,7 +431,7 @@ module Elastic
|
|
429
431
|
end
|
430
432
|
|
431
433
|
def apply_headers(client, options)
|
432
|
-
headers = options[:headers]
|
434
|
+
headers = options[:headers] || {}
|
433
435
|
headers[CONTENT_TYPE_STR] = find_value(headers, CONTENT_TYPE_REGEX) || DEFAULT_CONTENT_TYPE
|
434
436
|
headers[USER_AGENT_STR] = find_value(headers, USER_AGENT_REGEX) || user_agent_header(client)
|
435
437
|
client.headers[ACCEPT_ENCODING] = GZIP if use_compression?
|
@@ -444,7 +446,7 @@ module Elastic
|
|
444
446
|
end
|
445
447
|
end
|
446
448
|
|
447
|
-
def user_agent_header(
|
449
|
+
def user_agent_header(_client)
|
448
450
|
@user_agent ||= begin
|
449
451
|
meta = ["RUBY_VERSION: #{RUBY_VERSION}"]
|
450
452
|
if RbConfig::CONFIG && RbConfig::CONFIG['host_os']
|
@@ -455,7 +457,8 @@ module Elastic
|
|
455
457
|
end
|
456
458
|
|
457
459
|
def connection_headers(connection)
|
458
|
-
if defined?(Elastic::Transport::Transport::HTTP::Manticore) &&
|
460
|
+
if defined?(Elastic::Transport::Transport::HTTP::Manticore) &&
|
461
|
+
instance_of?(Elastic::Transport::Transport::HTTP::Manticore)
|
459
462
|
@request_options[:headers]
|
460
463
|
else
|
461
464
|
connection.connection.headers
|
@@ -18,7 +18,6 @@
|
|
18
18
|
module Elastic
|
19
19
|
module Transport
|
20
20
|
module Transport
|
21
|
-
|
22
21
|
# Generic client error
|
23
22
|
#
|
24
23
|
class Error < StandardError; end
|
@@ -78,14 +77,13 @@ module Elastic
|
|
78
77
|
505 => 'HTTPVersionNotSupported',
|
79
78
|
506 => 'VariantAlsoNegotiates',
|
80
79
|
510 => 'NotExtended'
|
81
|
-
}
|
80
|
+
}.freeze
|
82
81
|
|
83
|
-
ERRORS = HTTP_STATUSES.
|
82
|
+
ERRORS = HTTP_STATUSES.each_with_object({}) do |error, sum|
|
84
83
|
status, name = error
|
85
84
|
sum[status] = Errors.const_set name, Class.new(ServerError)
|
86
85
|
sum
|
87
86
|
end
|
88
|
-
|
89
87
|
end
|
90
88
|
end
|
91
89
|
end
|
@@ -37,31 +37,34 @@ module Elastic
|
|
37
37
|
body, headers = compress_request(body, headers)
|
38
38
|
|
39
39
|
case method
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
when 'HEAD'
|
41
|
+
connection.connection.set :nobody, true
|
42
|
+
when 'GET', 'POST', 'PUT', 'DELETE'
|
43
|
+
connection.connection.set :nobody, false
|
44
|
+
connection.connection.put_data = body if body
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
46
|
+
if headers
|
47
|
+
if connection.connection.headers
|
48
|
+
connection.connection.headers.merge!(headers)
|
49
|
+
else
|
50
|
+
connection.connection.headers = headers
|
52
51
|
end
|
52
|
+
end
|
53
53
|
|
54
|
-
|
54
|
+
else raise ArgumentError, "Unsupported HTTP method: #{method}"
|
55
55
|
end
|
56
56
|
|
57
57
|
connection.connection.http(method.to_sym)
|
58
|
+
header_string = connection.connection.header_str.to_s
|
58
59
|
|
59
|
-
response_headers =
|
60
|
-
response_headers
|
60
|
+
_response_status, *response_headers = header_string.split(/[\r\n]+/).map(&:strip)
|
61
|
+
response_headers = Hash[response_headers.flat_map { |s| s.scan(/^(\S+): (.+)/) }].transform_keys(&:downcase)
|
61
62
|
|
62
|
-
Response.new
|
63
|
-
|
64
|
-
|
63
|
+
Response.new(
|
64
|
+
connection.connection.response_code,
|
65
|
+
decompress_response(connection.connection.body_str),
|
66
|
+
response_headers
|
67
|
+
)
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
@@ -73,7 +76,7 @@ module Elastic
|
|
73
76
|
client = ::Curl::Easy.new
|
74
77
|
|
75
78
|
apply_headers(client, options)
|
76
|
-
client.url
|
79
|
+
client.url = __full_url(host)
|
77
80
|
|
78
81
|
if host[:user]
|
79
82
|
client.http_auth_types = host[:auth_type] || :basic
|
@@ -105,13 +108,13 @@ module Elastic
|
|
105
108
|
|
106
109
|
def user_agent_header(client)
|
107
110
|
@user_agent ||= begin
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
111
|
+
meta = ["RUBY_VERSION: #{RUBY_VERSION}"]
|
112
|
+
if RbConfig::CONFIG && RbConfig::CONFIG['host_os']
|
113
|
+
meta << "#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase} #{RbConfig::CONFIG['target_cpu']}"
|
114
|
+
end
|
115
|
+
meta << "Curb #{Curl::CURB_VERSION}"
|
116
|
+
"elastic-transport-ruby/#{VERSION} (#{meta.join('; ')})"
|
117
|
+
end
|
115
118
|
end
|
116
119
|
end
|
117
120
|
end
|
@@ -34,26 +34,27 @@ module Elastic
|
|
34
34
|
#
|
35
35
|
def perform_request(method, path, params = {}, body = nil, headers = nil, opts = {})
|
36
36
|
super do |connection, url|
|
37
|
-
headers =
|
38
|
-
if !headers.nil?
|
39
|
-
connection.connection.headers.merge(headers)
|
40
|
-
else
|
41
|
-
connection.connection.headers
|
42
|
-
end
|
43
|
-
else
|
44
|
-
headers
|
45
|
-
end
|
37
|
+
headers = parse_headers(headers, connection)
|
46
38
|
body = body ? __convert_to_json(body) : nil
|
47
39
|
body, headers = compress_request(body, headers)
|
48
40
|
|
49
|
-
response = connection.connection.run_request(
|
50
|
-
method.downcase.to_sym,
|
51
|
-
url,
|
52
|
-
body,
|
53
|
-
headers
|
54
|
-
)
|
41
|
+
response = connection.connection.run_request(method.downcase.to_sym, url, body, headers)
|
55
42
|
|
56
|
-
Response.new
|
43
|
+
Response.new(response.status, decompress_response(response.body), response.headers)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Merges headers already present in the connection and the ones passed in to perform_request
|
48
|
+
#
|
49
|
+
def parse_headers(headers, connection)
|
50
|
+
if connection.connection.headers
|
51
|
+
if !headers.nil?
|
52
|
+
connection.connection.headers.merge(headers)
|
53
|
+
else
|
54
|
+
connection.connection.headers
|
55
|
+
end
|
56
|
+
else
|
57
|
+
headers
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
@@ -73,10 +74,10 @@ module Elastic
|
|
73
74
|
#
|
74
75
|
def host_unreachable_exceptions
|
75
76
|
[
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
::Faraday::ConnectionFailed,
|
78
|
+
::Faraday::TimeoutError,
|
79
|
+
::Faraday.const_defined?(:ServerError) ? ::Faraday::ServerError : nil,
|
80
|
+
::Faraday::SSLError
|
80
81
|
].compact
|
81
82
|
end
|
82
83
|
|
@@ -84,13 +85,14 @@ module Elastic
|
|
84
85
|
|
85
86
|
def user_agent_header(client)
|
86
87
|
@user_agent ||= begin
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
88
|
+
meta = ["RUBY_VERSION: #{RUBY_VERSION}"]
|
89
|
+
if RbConfig::CONFIG && RbConfig::CONFIG['host_os']
|
90
|
+
meta << "#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase} " \
|
91
|
+
"#{RbConfig::CONFIG['target_cpu']}"
|
92
|
+
end
|
93
|
+
meta << client.headers[USER_AGENT_STR]
|
94
|
+
"elastic-transport-ruby/#{VERSION} (#{meta.join('; ')})"
|
95
|
+
end
|
94
96
|
end
|
95
97
|
end
|
96
98
|
end
|
@@ -162,7 +162,7 @@ module Elastic
|
|
162
162
|
private
|
163
163
|
|
164
164
|
def apply_headers(options)
|
165
|
-
headers = options[:headers]
|
165
|
+
headers = options[:headers] || options.dig(:transport_options, :headers) || {}
|
166
166
|
headers[CONTENT_TYPE_STR] = find_value(headers, CONTENT_TYPE_REGEX) || DEFAULT_CONTENT_TYPE
|
167
167
|
headers[USER_AGENT_STR] = find_value(headers, USER_AGENT_REGEX) || find_value(@request_options[:headers], USER_AGENT_REGEX) || user_agent_header
|
168
168
|
headers[ACCEPT_ENCODING] = GZIP if use_compression?
|
@@ -19,7 +19,8 @@ module Elastic
|
|
19
19
|
module Transport
|
20
20
|
module Transport
|
21
21
|
# Wraps the response from Elasticsearch.
|
22
|
-
# It provides `body`, `status` and `headers` methods
|
22
|
+
# It provides `body`, `status` and `headers` methods, but you can treat is as a hash and
|
23
|
+
# access the keys directly.
|
23
24
|
class Response
|
24
25
|
attr_reader :status, :body, :headers
|
25
26
|
|
@@ -28,7 +29,7 @@ module Elastic
|
|
28
29
|
# @param headers [Hash] Response headers
|
29
30
|
def initialize(status, body, headers = {})
|
30
31
|
@status, @body, @headers = status, body, headers
|
31
|
-
@body = body.force_encoding('UTF-8') if body.respond_to?(:force_encoding)
|
32
|
+
@body = body.force_encoding('UTF-8') if body.respond_to?(:force_encoding)
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -76,9 +76,7 @@ module Elastic
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def parse_publish_address(publish_address)
|
79
|
-
#
|
80
|
-
return parse_address_port(publish_address[6..-2]) if publish_address =~ /^inet\[.*\]$/
|
81
|
-
|
79
|
+
# publish_address is in the format hostname/ip:port
|
82
80
|
if publish_address =~ /\//
|
83
81
|
parts = publish_address.partition('/')
|
84
82
|
[ parts[0], parse_address_port(parts[2])[1] ]
|
@@ -105,7 +105,8 @@ describe Elastic::Transport::Transport::Base do
|
|
105
105
|
let(:arguments) do
|
106
106
|
{
|
107
107
|
hosts: ['http://unavailable:9200', 'http://unavailable:9201'],
|
108
|
-
retry_on_failure: 2
|
108
|
+
retry_on_failure: 2,
|
109
|
+
adapter: :net_http
|
109
110
|
}
|
110
111
|
end
|
111
112
|
|
@@ -129,7 +130,8 @@ describe Elastic::Transport::Transport::Base do
|
|
129
130
|
let(:arguments) do
|
130
131
|
{
|
131
132
|
hosts: ELASTICSEARCH_HOSTS,
|
132
|
-
retry_on_status: ['404']
|
133
|
+
retry_on_status: ['404'],
|
134
|
+
adapter: :net_http
|
133
135
|
}
|
134
136
|
end
|
135
137
|
|
@@ -191,8 +191,8 @@ describe Elastic::Transport::Client do
|
|
191
191
|
it 'uses Faraday NetHttp' do
|
192
192
|
expect(adapter).to eq Faraday::Adapter::NetHttp
|
193
193
|
end
|
194
|
-
end
|
195
|
-
end
|
194
|
+
end
|
195
|
+
end unless jruby?
|
196
196
|
|
197
197
|
context 'when the adapter is patron' do
|
198
198
|
let(:adapter) do
|
@@ -204,9 +204,10 @@ describe Elastic::Transport::Client do
|
|
204
204
|
end
|
205
205
|
|
206
206
|
it 'uses Faraday with the adapter' do
|
207
|
+
require 'faraday/patron'
|
207
208
|
expect(adapter).to eq Faraday::Adapter::Patron
|
208
209
|
end
|
209
|
-
end
|
210
|
+
end unless jruby?
|
210
211
|
|
211
212
|
context 'when the adapter is typhoeus' do
|
212
213
|
let(:adapter) do
|
@@ -214,6 +215,8 @@ describe Elastic::Transport::Client do
|
|
214
215
|
end
|
215
216
|
|
216
217
|
let(:client) do
|
218
|
+
require 'faraday/typhoeus' if is_faraday_v2?
|
219
|
+
|
217
220
|
described_class.new(adapter: :typhoeus, enable_meta_header: false)
|
218
221
|
end
|
219
222
|
|
@@ -234,7 +237,7 @@ describe Elastic::Transport::Client do
|
|
234
237
|
it 'uses Faraday with the adapter' do
|
235
238
|
expect(adapter).to eq Faraday::Adapter::Patron
|
236
239
|
end
|
237
|
-
end
|
240
|
+
end unless jruby?
|
238
241
|
|
239
242
|
context 'when the adapter can be detected', unless: jruby? do
|
240
243
|
around do |example|
|
@@ -274,7 +277,7 @@ describe Elastic::Transport::Client do
|
|
274
277
|
it 'sets the logger' do
|
275
278
|
expect(handlers).to include(Faraday::Response::Logger)
|
276
279
|
end
|
277
|
-
end
|
280
|
+
end unless jruby?
|
278
281
|
end
|
279
282
|
|
280
283
|
shared_examples_for 'a client that extracts hosts' do
|
@@ -1191,17 +1194,7 @@ describe Elastic::Transport::Client do
|
|
1191
1194
|
|
1192
1195
|
context 'when the client connects to Elasticsearch' do
|
1193
1196
|
let(:logger) do
|
1194
|
-
Logger.new(
|
1195
|
-
logger.formatter = proc do |severity, datetime, progname, msg|
|
1196
|
-
color = case severity
|
1197
|
-
when /INFO/ then :green
|
1198
|
-
when /ERROR|WARN|FATAL/ then :red
|
1199
|
-
when /DEBUG/ then :cyan
|
1200
|
-
else :white
|
1201
|
-
end
|
1202
|
-
ANSI.ansi(severity[0] + ' ', color, :faint) + ANSI.ansi(msg, :white, :faint) + "\n"
|
1203
|
-
end
|
1204
|
-
end unless ENV['QUIET']
|
1197
|
+
Logger.new($stderr) unless ENV['QUIET']
|
1205
1198
|
end
|
1206
1199
|
|
1207
1200
|
let(:port) do
|
@@ -1263,6 +1256,8 @@ describe Elastic::Transport::Client do
|
|
1263
1256
|
end
|
1264
1257
|
|
1265
1258
|
context 'when the Faraday adapter is set in the block' do
|
1259
|
+
require 'faraday/net_http_persistent' if is_faraday_v2?
|
1260
|
+
|
1266
1261
|
let(:client) do
|
1267
1262
|
Elastic::Transport::Client.new(host: ELASTICSEARCH_HOSTS.first, logger: logger) do |client|
|
1268
1263
|
client.adapter(:net_http_persistent)
|
@@ -1414,6 +1409,8 @@ describe Elastic::Transport::Client do
|
|
1414
1409
|
end
|
1415
1410
|
|
1416
1411
|
context 'when using the HTTPClient adapter' do
|
1412
|
+
require 'faraday/httpclient'
|
1413
|
+
|
1417
1414
|
let(:client) do
|
1418
1415
|
described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :httpclient, enable_meta_header: false)
|
1419
1416
|
end
|
@@ -155,7 +155,7 @@ describe Elastic::Transport::Client do
|
|
155
155
|
expect(headers).to include('x-elastic-client-meta' => meta)
|
156
156
|
|
157
157
|
Typhoeus = @klass if was_required
|
158
|
-
end
|
158
|
+
end
|
159
159
|
|
160
160
|
it 'sets adapter in the meta header' do
|
161
161
|
require 'typhoeus'
|
@@ -163,7 +163,7 @@ describe Elastic::Transport::Client do
|
|
163
163
|
meta = "#{meta_header},ty=#{Typhoeus::VERSION}"
|
164
164
|
expect(headers).to include('x-elastic-client-meta' => meta)
|
165
165
|
end
|
166
|
-
end
|
166
|
+
end unless jruby?
|
167
167
|
|
168
168
|
unless jruby?
|
169
169
|
let(:adapter) { :patron }
|
@@ -257,24 +257,6 @@ describe Elastic::Transport::Transport::Sniffer do
|
|
257
257
|
end
|
258
258
|
end
|
259
259
|
|
260
|
-
context 'when the address is IPv4' do
|
261
|
-
let(:publish_address) do
|
262
|
-
'inet[/127.0.0.1:9200]'
|
263
|
-
end
|
264
|
-
|
265
|
-
it 'parses the response' do
|
266
|
-
expect(hosts.size).to eq(1)
|
267
|
-
end
|
268
|
-
|
269
|
-
it 'correctly parses the host' do
|
270
|
-
expect(hosts[0][:host]).to eq('127.0.0.1')
|
271
|
-
end
|
272
|
-
|
273
|
-
it 'correctly parses the port' do
|
274
|
-
expect(hosts[0][:port]).to eq('9200')
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
260
|
context 'when the transport has :randomize_hosts option' do
|
279
261
|
let(:raw_response) do
|
280
262
|
{ 'nodes' => { 'n1' => { 'http' => { 'publish_address' => '127.0.0.1:9250' } },
|