elasticsearch-transport 7.10.0 → 7.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cec988f9a2a79c9458bc3974d3d52a541cba9b230de23b96df5f74a913de6524
4
- data.tar.gz: 2eb97ff41d033724456132546b642663074dc5859fe2f8a9aa9973dbbf85342d
3
+ metadata.gz: 07e3f02a3b166d00bcee76a0a39731ef5cc2c1aab442d4f6af2b4300a85661d6
4
+ data.tar.gz: 149090dcf60ef7f09637a42e23e33bcc78245872ff470bf064194fad59f2a19c
5
5
  SHA512:
6
- metadata.gz: df0608bf2a72da4d41ce9f7884d63f1279deccd317e1a8379846cee95d556d8f8c91af31049c6d1206b8a28087f4706f655c9a0429beda386d33b82a683dce09
7
- data.tar.gz: 8c37e0c4e02c890241981f42be1a9823d91e9c0c9d010e7193d3a46069448965752495a2e447db15a0f6318d35152c31162a997f3093958cd8e02f623e812cf9
6
+ metadata.gz: a4919e34440ab8a91c2feafb2383e44b518b6b1f122ef59ddf26e35a93c2d1e23ef49f3b7f267eff7a51fd57de671cc66742358b1265ab5211362865ae40127f
7
+ data.tar.gz: b7b9f51e9232c29203cb110bf9e7b1002cffcaac4c583051795e83e590dc4c7a6ea3fd887d0a617f4ed0cb36e0d0e8593ed64c802894990b9c5dbf7eed657773
data/Gemfile CHANGED
@@ -32,7 +32,7 @@ if File.exist? File.expand_path('../../elasticsearch/elasticsearch.gemspec', __F
32
32
  gem 'elasticsearch', path: File.expand_path('../../elasticsearch', __FILE__), require: false
33
33
  end
34
34
 
35
- group :development do
35
+ group :development, :test do
36
36
  gem 'rspec'
37
37
  if defined?(JRUBY_VERSION)
38
38
  gem 'pry-nav'
data/README.md CHANGED
@@ -136,7 +136,7 @@ Please see below for an exception to this when connecting using an Elastic Cloud
136
136
 
137
137
  If you are using [Elastic Cloud](https://www.elastic.co/cloud), you can provide your cloud id to the client.
138
138
  You must supply your username and password separately, and optionally a port. If no port is supplied,
139
- port 9243 will be used.
139
+ port 443 will be used.
140
140
 
141
141
  Note: Do not enable sniffing when using Elastic Cloud. The nodes are behind a load balancer so
142
142
  Elastic Cloud will take care of everything for you.
@@ -187,18 +187,24 @@ Elasticsearch::Client.new(
187
187
 
188
188
  ### Logging
189
189
 
190
- To log requests and responses to standard output with the default logger (an instance of Ruby's {::Logger} class),
191
- set the `log` argument:
190
+ To log requests and responses to standard output with the default logger (an instance of Ruby's {::Logger} class), set the `log` argument to true:
192
191
 
193
192
  ```ruby
194
- Elasticsearch::Client.new log: true
193
+ Elasticsearch::Client.new(log: true)
194
+ ```
195
+
196
+ You can also use [ecs-logging](https://github.com/elastic/ecs-logging-ruby). `ecs-logging` is a set of libraries that allows you to transform your application logs to structured logs that comply with the [Elastic Common Schema (ECS)](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html):
197
+
198
+ ```ruby
199
+ logger = EcsLogging::Logger.new($stdout)
200
+ Elasticsearch::Client.new(logger: logger)
195
201
  ```
196
202
 
197
203
 
198
204
  To trace requests and responses in the _Curl_ format, set the `trace` argument:
199
205
 
200
206
  ```ruby
201
- Elasticsearch::Client.new trace: true
207
+ Elasticsearch::Client.new(trace: true)
202
208
  ```
203
209
 
204
210
  You can customize the default logger or tracer:
@@ -211,7 +217,7 @@ You can customize the default logger or tracer:
211
217
  Or, you can use a custom `::Logger` instance:
212
218
 
213
219
  ```ruby
214
- Elasticsearch::Client.new logger: Logger.new(STDERR)
220
+ Elasticsearch::Client.new(logger: Logger.new(STDERR))
215
221
  ```
216
222
 
217
223
  You can pass the client any conforming logger implementation:
@@ -223,7 +229,7 @@ log = Logging.logger['elasticsearch']
223
229
  log.add_appenders Logging.appenders.stdout
224
230
  log.level = :info
225
231
 
226
- client = Elasticsearch::Client.new logger: log
232
+ client = Elasticsearch::Client.new(logger: log)
227
233
  ```
228
234
 
229
235
  ### Custom HTTP Headers
@@ -16,6 +16,7 @@
16
16
  # under the License.
17
17
 
18
18
  require 'base64'
19
+ require 'elasticsearch/transport/meta_header'
19
20
 
20
21
  module Elasticsearch
21
22
  module Transport
@@ -25,6 +26,7 @@ module Elasticsearch
25
26
  # See {file:README.md README} for usage and code examples.
26
27
  #
27
28
  class Client
29
+ include MetaHeader
28
30
  DEFAULT_TRANSPORT_CLASS = Transport::HTTP::Faraday
29
31
 
30
32
  DEFAULT_LOGGER = lambda do
@@ -49,9 +51,15 @@ module Elasticsearch
49
51
  DEFAULT_HOST = 'localhost:9200'.freeze
50
52
 
51
53
  # The default port to use if connecting using a Cloud ID.
54
+ # Updated from 9243 to 443 in client version 7.10.1
52
55
  #
53
56
  # @since 7.2.0
54
- DEFAULT_CLOUD_PORT = 9243
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
55
63
 
56
64
  # Returns the transport object.
57
65
  #
@@ -114,8 +122,11 @@ module Elasticsearch
114
122
  #
115
123
  # @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key`
116
124
  # joined by a colon as a String, or a hash with the `id` and `api_key` values.
117
- # @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client. This
118
- # will be prepended to the id you set before each request if you're using X-Opaque-Id
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)
119
130
  #
120
131
  # @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block
121
132
  #
@@ -130,6 +141,7 @@ module Elasticsearch
130
141
  @arguments[:randomize_hosts] ||= false
131
142
  @arguments[:transport_options] ||= {}
132
143
  @arguments[:http] ||= {}
144
+ @arguments[:enable_meta_header] = arguments.fetch(:enable_meta_header) { true }
133
145
  @options[:http] ||= {}
134
146
 
135
147
  set_api_key if (@api_key = @arguments[:api_key])
@@ -152,15 +164,18 @@ module Elasticsearch
152
164
  if @arguments[:transport]
153
165
  @transport = @arguments[:transport]
154
166
  else
155
- transport_class = @arguments[:transport_class] || DEFAULT_TRANSPORT_CLASS
156
- if transport_class == Transport::HTTP::Faraday
157
- @transport = transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
158
- faraday.adapter(@arguments[:adapter] || __auto_detect_adapter)
159
- block&.call faraday
160
- end
161
- else
162
- @transport = transport_class.new(hosts: @seeds, options: @arguments)
163
- end
167
+ @transport_class = @arguments[:transport_class] || DEFAULT_TRANSPORT_CLASS
168
+ @transport = if @transport_class == Transport::HTTP::Faraday
169
+ @arguments[:adapter] ||= __auto_detect_adapter
170
+ set_meta_header # from include MetaHeader
171
+ @transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
172
+ faraday.adapter(@arguments[:adapter])
173
+ block&.call faraday
174
+ end
175
+ else
176
+ set_meta_header # from include MetaHeader
177
+ @transport_class.new(hosts: @seeds, options: @arguments)
178
+ end
164
179
  end
165
180
  end
166
181
 
@@ -180,13 +195,17 @@ module Elasticsearch
180
195
 
181
196
  def set_api_key
182
197
  @api_key = __encode(@api_key) if @api_key.is_a? Hash
198
+ add_header('Authorization' => "ApiKey #{@api_key}")
199
+ @arguments.delete(:user)
200
+ @arguments.delete(:password)
201
+ end
202
+
203
+ def add_header(header)
183
204
  headers = @arguments[:transport_options]&.[](:headers) || {}
184
- headers.merge!('Authorization' => "ApiKey #{@api_key}")
205
+ headers.merge!(header)
185
206
  @arguments[:transport_options].merge!(
186
207
  headers: headers
187
208
  )
188
- @arguments.delete(:user)
189
- @arguments.delete(:password)
190
209
  end
191
210
 
192
211
  def extract_cloud_creds(arguments)
@@ -243,36 +262,38 @@ module Elasticsearch
243
262
 
244
263
  def __parse_host(host)
245
264
  host_parts = case host
246
- when String
247
- if host =~ /^[a-z]+\:\/\//
248
- # Construct a new `URI::Generic` directly from the array returned by URI::split.
249
- # This avoids `URI::HTTP` and `URI::HTTPS`, which supply default ports.
250
- uri = URI::Generic.new(*URI.split(host))
251
-
252
- { :scheme => uri.scheme,
253
- :user => uri.user,
254
- :password => uri.password,
255
- :host => uri.host,
256
- :path => uri.path,
257
- :port => uri.port }
258
- else
259
- host, port = host.split(':')
260
- { :host => host,
261
- :port => port }
262
- end
263
- when URI
264
- { :scheme => host.scheme,
265
- :user => host.user,
266
- :password => host.password,
267
- :host => host.host,
268
- :path => host.path,
269
- :port => host.port }
270
- when Hash
271
- host
272
- else
273
- raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
274
- end
275
-
265
+ when String
266
+ if host =~ /^[a-z]+\:\/\//
267
+ # Construct a new `URI::Generic` directly from the array returned by URI::split.
268
+ # This avoids `URI::HTTP` and `URI::HTTPS`, which supply default ports.
269
+ uri = URI::Generic.new(*URI.split(host))
270
+ default_port = uri.scheme == 'https' ? 443 : DEFAULT_PORT
271
+ {
272
+ scheme: uri.scheme,
273
+ user: uri.user,
274
+ password: uri.password,
275
+ host: uri.host,
276
+ path: uri.path,
277
+ port: uri.port || default_port
278
+ }
279
+ else
280
+ host, port = host.split(':')
281
+ { host: host, port: port }
282
+ end
283
+ when URI
284
+ {
285
+ scheme: host.scheme,
286
+ user: host.user,
287
+ password: host.password,
288
+ host: host.host,
289
+ path: host.path,
290
+ port: host.port
291
+ }
292
+ when Hash
293
+ host
294
+ else
295
+ raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
296
+ end
276
297
  if @api_key
277
298
  # Remove Basic Auth if using API KEY
278
299
  host_parts.delete(:user)
@@ -0,0 +1,120 @@
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
+
23
+ # Methods for the Elastic meta header used by Cloud.
24
+ # X-Elastic-Client-Meta HTTP header which is used by Elastic Cloud and can be disabled when
25
+ # instantiating the Client with the :enable_meta_header parameter set to `false`.
26
+ #
27
+ module MetaHeader
28
+ def set_meta_header
29
+ return if @arguments[:enable_meta_header] == false
30
+
31
+ service, version = meta_header_service_version
32
+
33
+ meta_headers = {
34
+ service.to_sym => version,
35
+ rb: RUBY_VERSION,
36
+ t: Elasticsearch::Transport::VERSION
37
+ }
38
+ meta_headers.merge!(meta_header_engine) if meta_header_engine
39
+ meta_headers.merge!(meta_header_adapter) if meta_header_adapter
40
+
41
+ add_header({ 'x-elastic-client-meta' => meta_headers.map { |k, v| "#{k}=#{v}" }.join(',') })
42
+ end
43
+
44
+ def meta_header_service_version
45
+ if defined?(Elastic::META_HEADER_SERVICE_VERSION)
46
+ Elastic::META_HEADER_SERVICE_VERSION
47
+ elsif defined?(Elasticsearch::VERSION)
48
+ [:es, client_meta_version(Elasticsearch::VERSION)]
49
+ else
50
+ [:es, client_meta_version(Elasticsearch::Transport::VERSION)]
51
+ end
52
+ end
53
+
54
+ # We return the current version if it's a release, but if it's a pre/alpha/beta release we
55
+ # return <VERSION_NUMBER>p
56
+ #
57
+ def client_meta_version(version)
58
+ regexp = /^([0-9]+\.[0-9]+\.[0-9]+)(\.?[a-z0-9.-]+)?$/
59
+ match = version.match(regexp)
60
+ return "#{match[1]}p" if (match[2])
61
+
62
+ version
63
+ end
64
+
65
+ def meta_header_engine
66
+ case RUBY_ENGINE
67
+ when 'ruby'
68
+ {}
69
+ when 'jruby'
70
+ { jv: ENV_JAVA['java.version'], jr: JRUBY_VERSION }
71
+ when 'rbx'
72
+ { rbx: RUBY_VERSION }
73
+ else
74
+ { RUBY_ENGINE.to_sym => RUBY_VERSION }
75
+ end
76
+ end
77
+
78
+ # This function tries to define the version for the Faraday adapter. If it hasn't been loaded
79
+ # by the time we're calling this method, it's going to report the adapter (if we know it) but
80
+ # return 0 as the version. It won't report anything when using a custom adapter we don't
81
+ # identify.
82
+ #
83
+ # Returns a Hash<adapter_alias, version>
84
+ #
85
+ def meta_header_adapter
86
+ if @transport_class == Transport::HTTP::Faraday
87
+ version = '0'
88
+ adapter_version = case @arguments[:adapter]
89
+ when :patron
90
+ version = Patron::VERSION if defined?(::Patron::VERSION)
91
+ {pt: version}
92
+ when :net_http
93
+ version = if defined?(Net::HTTP::VERSION)
94
+ Net::HTTP::VERSION
95
+ elsif defined?(Net::HTTP::HTTPVersion)
96
+ Net::HTTP::HTTPVersion
97
+ end
98
+ {nh: version}
99
+ when :typhoeus
100
+ version = Typhoeus::VERSION if defined?(::Typhoeus::VERSION)
101
+ {ty: version}
102
+ when :httpclient
103
+ version = HTTPClient::VERSION if defined?(HTTPClient::VERSION)
104
+ {hc: version}
105
+ when :net_http_persistent
106
+ version = Net::HTTP::Persistent::VERSION if defined?(Net::HTTP::Persistent::VERSION)
107
+ {np: version}
108
+ else
109
+ {}
110
+ end
111
+ {fd: Faraday::VERSION}.merge(adapter_version)
112
+ elsif defined?(Transport::HTTP::Curb) && @transport_class == Transport::HTTP::Curb
113
+ {cl: Curl::CURB_VERSION}
114
+ elsif defined?(Transport::HTTP::Manticore) && @transport_class == Transport::HTTP::Manticore
115
+ {mc: Manticore::VERSION}
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -33,9 +33,17 @@ module Elasticsearch
33
33
  # @return [Response]
34
34
  # @see Transport::Base#perform_request
35
35
  #
36
- def perform_request(method, path, params={}, body=nil, headers=nil, opts={})
36
+ def perform_request(method, path, params = {}, body = nil, headers = nil, opts = {})
37
37
  super do |connection, url|
38
- headers = headers || connection.connection.headers
38
+ headers = if connection.connection.headers
39
+ if !headers.nil?
40
+ connection.connection.headers.merge(headers)
41
+ else
42
+ connection.connection.headers
43
+ end
44
+ else
45
+ headers
46
+ end
39
47
 
40
48
  response = connection.connection.run_request(method.downcase.to_sym,
41
49
  url,
@@ -17,6 +17,6 @@
17
17
 
18
18
  module Elasticsearch
19
19
  module Transport
20
- VERSION = "7.10.0"
20
+ VERSION = '7.11.2'.freeze
21
21
  end
22
22
  end
@@ -246,7 +246,7 @@ describe Elasticsearch::Transport::Client do
246
246
  end
247
247
 
248
248
  let(:client) do
249
- described_class.new(adapter: :patron)
249
+ described_class.new(adapter: :patron, enable_meta_header: false)
250
250
  end
251
251
 
252
252
  it 'uses Faraday with the adapter' do
@@ -260,7 +260,7 @@ describe Elasticsearch::Transport::Client do
260
260
  end
261
261
 
262
262
  let(:client) do
263
- described_class.new(adapter: :typhoeus)
263
+ described_class.new(adapter: :typhoeus, enable_meta_header: false)
264
264
  end
265
265
 
266
266
  it 'uses Faraday with the adapter' do
@@ -274,7 +274,7 @@ describe Elasticsearch::Transport::Client do
274
274
  end
275
275
 
276
276
  let(:client) do
277
- described_class.new('adapter' => :patron)
277
+ described_class.new(adapter: :patron, enable_meta_header: false)
278
278
  end
279
279
 
280
280
  it 'uses Faraday with the adapter' do
@@ -344,24 +344,19 @@ describe Elasticsearch::Transport::Client do
344
344
  expect(hosts[0][:protocol]).to eq('https')
345
345
  expect(hosts[0][:user]).to eq('elastic')
346
346
  expect(hosts[0][:password]).to eq('changeme')
347
- expect(hosts[0][:port]).to eq(9243)
347
+ expect(hosts[0][:port]).to eq(443)
348
348
  end
349
349
 
350
350
  it 'creates the correct full url' do
351
351
  expect(
352
352
  client.transport.__full_url(client.transport.hosts[0])
353
- ).to eq('https://elastic:changeme@abcd.localhost:9243')
353
+ ).to eq('https://elastic:changeme@abcd.localhost:443')
354
354
  end
355
355
 
356
356
  context 'when a port is specified' do
357
357
 
358
358
  let(:client) do
359
- described_class.new(
360
- cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
361
- user: 'elastic',
362
- password: 'changeme',
363
- port: 9200
364
- )
359
+ described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port: 9250)
365
360
  end
366
361
 
367
362
  it 'sets the specified port along with the cloud credentials' do
@@ -369,11 +364,11 @@ describe Elasticsearch::Transport::Client do
369
364
  expect(hosts[0][:protocol]).to eq('https')
370
365
  expect(hosts[0][:user]).to eq('elastic')
371
366
  expect(hosts[0][:password]).to eq('changeme')
372
- expect(hosts[0][:port]).to eq(9200)
367
+ expect(hosts[0][:port]).to eq(9250)
373
368
  end
374
369
 
375
370
  it 'creates the correct full url' do
376
- expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:9200')
371
+ expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:9250')
377
372
  end
378
373
  end
379
374
 
@@ -396,13 +391,13 @@ describe Elasticsearch::Transport::Client do
396
391
  expect(hosts[0][:protocol]).to eq('https')
397
392
  expect(hosts[0][:user]).to eq('elasticfantastic')
398
393
  expect(hosts[0][:password]).to eq('tobechanged')
399
- expect(hosts[0][:port]).to eq(9243)
394
+ expect(hosts[0][:port]).to eq(443)
400
395
  end
401
396
 
402
397
  it 'creates the correct full url' do
403
398
  expect(
404
399
  client.transport.__full_url(client.transport.hosts[0])
405
- ).to eq('https://elasticfantastic:tobechanged@abcd.localhost:9243')
400
+ ).to eq('https://elasticfantastic:tobechanged@abcd.localhost:443')
406
401
  end
407
402
  end
408
403
 
@@ -424,13 +419,13 @@ describe Elasticsearch::Transport::Client do
424
419
  expect(hosts[0][:protocol]).to eq('https')
425
420
  expect(hosts[0][:user]).to eq('elasticfantastic')
426
421
  expect(hosts[0][:password]).to eq('changeme')
427
- expect(hosts[0][:port]).to eq(9243)
422
+ expect(hosts[0][:port]).to eq(443)
428
423
  end
429
424
 
430
425
  it 'creates the correct full url' do
431
426
  expect(
432
427
  client.transport.__full_url(client.transport.hosts[0])
433
- ).to eq('https://elasticfantastic:changeme@abcd.localhost:9243')
428
+ ).to eq('https://elasticfantastic:changeme@abcd.localhost:443')
434
429
  end
435
430
  end
436
431
 
@@ -482,112 +477,248 @@ describe Elasticsearch::Transport::Client do
482
477
 
483
478
  shared_examples_for 'a client that extracts hosts' do
484
479
 
485
- context 'when the hosts are a String' do
480
+ context 'when the host is a String' do
486
481
 
487
- let(:host) do
488
- 'myhost'
489
- end
482
+ context 'when there is a protocol specified' do
490
483
 
491
- it 'extracts the host' do
492
- expect(hosts[0][:host]).to eq('myhost')
493
- expect(hosts[0][:protocol]).to eq('http')
494
- expect(hosts[0][:port]).to be(9200)
495
- end
484
+ context 'when credentials are specified \'http://USERNAME:PASSWORD@myhost:8080\'' do
496
485
 
497
- context 'when IPv6 format is used' do
486
+ let(:host) do
487
+ 'http://USERNAME:PASSWORD@myhost:8080'
488
+ end
498
489
 
499
- around do |example|
500
- original_setting = Faraday.ignore_env_proxy
501
- Faraday.ignore_env_proxy = true
502
- example.run
503
- Faraday.ignore_env_proxy = original_setting
504
- end
490
+ it 'extracts the credentials' do
491
+ expect(hosts[0][:user]).to eq('USERNAME')
492
+ expect(hosts[0][:password]).to eq('PASSWORD')
493
+ end
505
494
 
506
- let(:host) do
507
- 'https://[2090:db8:85a3:9811::1f]:8080'
508
- end
495
+ it 'extracts the host' do
496
+ expect(hosts[0][:host]).to eq('myhost')
497
+ end
509
498
 
510
- it 'extracts the host' do
511
- expect(hosts[0][:host]).to eq('[2090:db8:85a3:9811::1f]')
512
- expect(hosts[0][:scheme]).to eq('https')
513
- expect(hosts[0][:port]).to be(8080)
499
+ it 'extracts the port' do
500
+ expect(hosts[0][:port]).to be(8080)
501
+ end
514
502
  end
515
503
 
516
- it 'creates the correct full url' do
517
- expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://[2090:db8:85a3:9811::1f]:8080')
518
- end
519
- end
504
+ context 'when there is a trailing slash \'http://myhost/\'' do
520
505
 
521
- context 'when a path is specified' do
506
+ let(:host) do
507
+ 'http://myhost/'
508
+ end
522
509
 
523
- let(:host) do
524
- 'https://myhost:8080/api'
525
- end
510
+ it 'extracts the host' do
511
+ expect(hosts[0][:host]).to eq('myhost')
512
+ expect(hosts[0][:scheme]).to eq('http')
513
+ expect(hosts[0][:path]).to eq('')
514
+ end
526
515
 
527
- it 'extracts the host' do
528
- expect(hosts[0][:host]).to eq('myhost')
529
- expect(hosts[0][:scheme]).to eq('https')
530
- expect(hosts[0][:path]).to eq('/api')
531
- expect(hosts[0][:port]).to be(8080)
516
+ it 'extracts the scheme' do
517
+ expect(hosts[0][:scheme]).to eq('http')
518
+ end
519
+
520
+ it 'extracts the path' do
521
+ expect(hosts[0][:path]).to eq('')
522
+ end
532
523
  end
533
- end
534
524
 
535
- context 'when a scheme is specified' do
525
+ context 'when there is a trailing slash with a path \'http://myhost/foo/bar/\'' do
536
526
 
537
- let(:host) do
538
- 'https://myhost:8080'
539
- end
527
+ let(:host) do
528
+ 'http://myhost/foo/bar/'
529
+ end
540
530
 
541
- it 'extracts the host' do
542
- expect(hosts[0][:host]).to eq('myhost')
543
- expect(hosts[0][:scheme]).to eq('https')
544
- expect(hosts[0][:port]).to be(8080)
531
+ it 'extracts the host' do
532
+ expect(hosts[0][:host]).to eq('myhost')
533
+ expect(hosts[0][:scheme]).to eq('http')
534
+ expect(hosts[0][:path]).to eq('/foo/bar')
535
+ end
545
536
  end
546
- end
547
537
 
548
- context 'when credentials are specified' do
538
+ context 'when the protocol is http' do
549
539
 
550
- let(:host) do
551
- 'http://USERNAME:PASSWORD@myhost:8080'
552
- end
540
+ context 'when there is no port specified \'http://myhost\'' do
553
541
 
554
- it 'extracts the host' do
555
- expect(hosts[0][:host]).to eq('myhost')
556
- expect(hosts[0][:scheme]).to eq('http')
557
- expect(hosts[0][:user]).to eq('USERNAME')
558
- expect(hosts[0][:password]).to eq('PASSWORD')
559
- expect(hosts[0][:port]).to be(8080)
560
- end
561
- end
542
+ let(:host) do
543
+ 'http://myhost'
544
+ end
562
545
 
563
- context 'when there is a trailing slash' do
546
+ it 'extracts the host' do
547
+ expect(hosts[0][:host]).to eq('myhost')
548
+ end
564
549
 
565
- let(:host) do
566
- 'http://myhost/'
550
+ it 'extracts the protocol' do
551
+ expect(hosts[0][:protocol]).to eq('http')
552
+ end
553
+
554
+ it 'defaults to port 9200' do
555
+ expect(hosts[0][:port]).to be(9200)
556
+ end
557
+ end
558
+
559
+ context 'when there is a port specified \'http://myhost:7101\'' do
560
+
561
+ let(:host) do
562
+ 'http://myhost:7101'
563
+ end
564
+
565
+ it 'extracts the host' do
566
+ expect(hosts[0][:host]).to eq('myhost')
567
+ end
568
+
569
+ it 'extracts the protocol' do
570
+ expect(hosts[0][:protocol]).to eq('http')
571
+ end
572
+
573
+ it 'extracts the port' do
574
+ expect(hosts[0][:port]).to be(7101)
575
+ end
576
+
577
+ context 'when there is a path specified \'http://myhost:7101/api\'' do
578
+
579
+ let(:host) do
580
+ 'http://myhost:7101/api'
581
+ end
582
+
583
+ it 'sets the path' do
584
+ expect(hosts[0][:host]).to eq('myhost')
585
+ expect(hosts[0][:protocol]).to eq('http')
586
+ expect(hosts[0][:path]).to eq('/api')
587
+ expect(hosts[0][:port]).to be(7101)
588
+ end
589
+
590
+ it 'extracts the host' do
591
+ expect(hosts[0][:host]).to eq('myhost')
592
+ end
593
+
594
+ it 'extracts the protocol' do
595
+ expect(hosts[0][:protocol]).to eq('http')
596
+ end
597
+
598
+ it 'extracts the port' do
599
+ expect(hosts[0][:port]).to be(7101)
600
+ end
601
+
602
+ it 'extracts the path' do
603
+ expect(hosts[0][:path]).to eq('/api')
604
+ end
605
+ end
606
+ end
567
607
  end
568
608
 
569
- it 'extracts the host' do
570
- expect(hosts[0][:host]).to eq('myhost')
571
- expect(hosts[0][:scheme]).to eq('http')
572
- expect(hosts[0][:path]).to eq('')
609
+ context 'when the protocol is https' do
610
+
611
+ context 'when there is no port specified \'https://myhost\'' do
612
+
613
+ let(:host) do
614
+ 'https://myhost'
615
+ end
616
+
617
+ it 'extracts the host' do
618
+ expect(hosts[0][:host]).to eq('myhost')
619
+ end
620
+
621
+ it 'extracts the protocol' do
622
+ expect(hosts[0][:protocol]).to eq('https')
623
+ end
624
+
625
+ it 'defaults to port 443' do
626
+ expect(hosts[0][:port]).to be(443)
627
+ end
628
+ end
629
+
630
+ context 'when there is a port specified \'https://myhost:7101\'' do
631
+
632
+ let(:host) do
633
+ 'https://myhost:7101'
634
+ end
635
+
636
+ it 'extracts the host' do
637
+ expect(hosts[0][:host]).to eq('myhost')
638
+ end
639
+
640
+ it 'extracts the protocol' do
641
+ expect(hosts[0][:protocol]).to eq('https')
642
+ end
643
+
644
+ it 'extracts the port' do
645
+ expect(hosts[0][:port]).to be(7101)
646
+ end
647
+
648
+ context 'when there is a path specified \'https://myhost:7101/api\'' do
649
+
650
+ let(:host) do
651
+ 'https://myhost:7101/api'
652
+ end
653
+
654
+ it 'extracts the host' do
655
+ expect(hosts[0][:host]).to eq('myhost')
656
+ end
657
+
658
+ it 'extracts the protocol' do
659
+ expect(hosts[0][:protocol]).to eq('https')
660
+ end
661
+
662
+ it 'extracts the port' do
663
+ expect(hosts[0][:port]).to be(7101)
664
+ end
665
+
666
+ it 'extracts the path' do
667
+ expect(hosts[0][:path]).to eq('/api')
668
+ end
669
+ end
670
+ end
671
+
672
+ context 'when IPv6 format is used' do
673
+
674
+ around do |example|
675
+ original_setting = Faraday.ignore_env_proxy
676
+ Faraday.ignore_env_proxy = true
677
+ example.run
678
+ Faraday.ignore_env_proxy = original_setting
679
+ end
680
+
681
+ let(:host) do
682
+ 'https://[2090:db8:85a3:9811::1f]:8080'
683
+ end
684
+
685
+ it 'extracts the host' do
686
+ expect(hosts[0][:host]).to eq('[2090:db8:85a3:9811::1f]')
687
+ end
688
+
689
+ it 'extracts the protocol' do
690
+ expect(hosts[0][:protocol]).to eq('https')
691
+ end
692
+
693
+ it 'extracts the port' do
694
+ expect(hosts[0][:port]).to be(8080)
695
+ end
696
+
697
+ it 'creates the correct full url' do
698
+ expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://[2090:db8:85a3:9811::1f]:8080')
699
+ end
700
+ end
573
701
  end
574
702
  end
575
703
 
576
- context 'when there is a trailing slash with a path' do
704
+ context 'when no protocol is specified \'myhost\'' do
577
705
 
578
706
  let(:host) do
579
- 'http://myhost/foo/bar/'
707
+ 'myhost'
580
708
  end
581
709
 
582
- it 'extracts the host' do
710
+ it 'defaults to http' do
583
711
  expect(hosts[0][:host]).to eq('myhost')
584
- expect(hosts[0][:scheme]).to eq('http')
585
- expect(hosts[0][:path]).to eq('/foo/bar')
712
+ expect(hosts[0][:protocol]).to eq('http')
713
+ end
714
+
715
+ it 'uses port 9200' do
716
+ expect(hosts[0][:port]).to be(9200)
586
717
  end
587
718
  end
588
719
  end
589
720
 
590
- context 'when the hosts are a Hash' do
721
+ context 'when the host is a Hash' do
591
722
 
592
723
  let(:host) do
593
724
  { :host => 'myhost', :scheme => 'https' }
@@ -595,7 +726,13 @@ describe Elasticsearch::Transport::Client do
595
726
 
596
727
  it 'extracts the host' do
597
728
  expect(hosts[0][:host]).to eq('myhost')
598
- expect(hosts[0][:scheme]).to eq('https')
729
+ end
730
+
731
+ it 'extracts the protocol' do
732
+ expect(hosts[0][:protocol]).to eq('https')
733
+ end
734
+
735
+ it 'extracts the port' do
599
736
  expect(hosts[0][:port]).to be(9200)
600
737
  end
601
738
 
@@ -654,7 +791,13 @@ describe Elasticsearch::Transport::Client do
654
791
 
655
792
  it 'extracts the host' do
656
793
  expect(hosts[0][:host]).to eq('myhost')
794
+ end
795
+
796
+ it 'extracts the protocol' do
657
797
  expect(hosts[0][:scheme]).to eq('https')
798
+ end
799
+
800
+ it 'converts the port to an integer' do
658
801
  expect(hosts[0][:port]).to be(443)
659
802
  end
660
803
  end
@@ -667,7 +810,13 @@ describe Elasticsearch::Transport::Client do
667
810
 
668
811
  it 'extracts the host' do
669
812
  expect(hosts[0][:host]).to eq('myhost')
813
+ end
814
+
815
+ it 'extracts the protocol' do
670
816
  expect(hosts[0][:scheme]).to eq('https')
817
+ end
818
+
819
+ it 'extracts port as an integer' do
671
820
  expect(hosts[0][:port]).to be(443)
672
821
  end
673
822
  end
@@ -681,7 +830,13 @@ describe Elasticsearch::Transport::Client do
681
830
 
682
831
  it 'extracts the host' do
683
832
  expect(hosts[0][:host]).to eq('myhost')
833
+ end
834
+
835
+ it 'extracts the protocol' do
684
836
  expect(hosts[0][:scheme]).to eq('https')
837
+ end
838
+
839
+ it 'converts the port to an integer' do
685
840
  expect(hosts[0][:port]).to be(9200)
686
841
  end
687
842
 
@@ -693,7 +848,13 @@ describe Elasticsearch::Transport::Client do
693
848
 
694
849
  it 'extracts the host' do
695
850
  expect(hosts[0][:host]).to eq('myhost')
851
+ end
852
+
853
+ it 'extracts the protocol' do
696
854
  expect(hosts[0][:scheme]).to eq('https')
855
+ end
856
+
857
+ it 'converts the port to an integer' do
697
858
  expect(hosts[0][:port]).to be(443)
698
859
  end
699
860
  end
@@ -706,7 +867,13 @@ describe Elasticsearch::Transport::Client do
706
867
 
707
868
  it 'extracts the host' do
708
869
  expect(hosts[0][:host]).to eq('myhost')
870
+ end
871
+
872
+ it 'extracts the protocol' do
709
873
  expect(hosts[0][:scheme]).to eq('https')
874
+ end
875
+
876
+ it 'extracts port as an integer' do
710
877
  expect(hosts[0][:port]).to be(443)
711
878
  end
712
879
  end
@@ -722,7 +889,13 @@ describe Elasticsearch::Transport::Client do
722
889
 
723
890
  it 'extracts the host' do
724
891
  expect(hosts[0][:host]).to eq('myhost')
892
+ end
893
+
894
+ it 'extracts the protocol' do
725
895
  expect(hosts[0][:protocol]).to eq('http')
896
+ end
897
+
898
+ it 'defaults to port 9200' do
726
899
  expect(hosts[0][:port]).to be(9200)
727
900
  end
728
901
  end
@@ -735,20 +908,13 @@ describe Elasticsearch::Transport::Client do
735
908
 
736
909
  it 'extracts the host' do
737
910
  expect(hosts[0][:host]).to eq('myhost')
738
- expect(hosts[0][:protocol]).to eq('http')
739
- expect(hosts[0][:port]).to be(9200)
740
911
  end
741
- end
742
-
743
- context 'when there is one host with a protocol and no port' do
744
912
 
745
- let(:host) do
746
- ['http://myhost']
913
+ it 'extracts the protocol' do
914
+ expect(hosts[0][:scheme]).to eq('http')
747
915
  end
748
916
 
749
- it 'extracts the host' do
750
- expect(hosts[0][:host]).to eq('myhost')
751
- expect(hosts[0][:protocol]).to eq('http')
917
+ it 'defaults to port 9200' do
752
918
  expect(hosts[0][:port]).to be(9200)
753
919
  end
754
920
  end
@@ -773,7 +939,7 @@ describe Elasticsearch::Transport::Client do
773
939
  end
774
940
  end
775
941
 
776
- context 'when there is one host with a scheme, protocol and no port' do
942
+ context 'when there is one host with a protocol and no port' do
777
943
 
778
944
  let(:host) do
779
945
  ['https://myhost']
@@ -781,12 +947,18 @@ describe Elasticsearch::Transport::Client do
781
947
 
782
948
  it 'extracts the host' do
783
949
  expect(hosts[0][:host]).to eq('myhost')
784
- expect(hosts[0][:protocol]).to eq('https')
785
- expect(hosts[0][:port]).to be(9200)
950
+ end
951
+
952
+ it 'extracts the protocol' do
953
+ expect(hosts[0][:scheme]).to eq('https')
954
+ end
955
+
956
+ it 'defaults to port 443' do
957
+ expect(hosts[0][:port]).to be(443)
786
958
  end
787
959
  end
788
960
 
789
- context 'when there is one host with a scheme, protocol, path, and no port' do
961
+ context 'when there is one host with a protocol, path, and no port' do
790
962
 
791
963
  let(:host) do
792
964
  ['http://myhost/foo/bar']
@@ -794,9 +966,18 @@ describe Elasticsearch::Transport::Client do
794
966
 
795
967
  it 'extracts the host' do
796
968
  expect(hosts[0][:host]).to eq('myhost')
797
- expect(hosts[0][:protocol]).to eq('http')
969
+ end
970
+
971
+ it 'extracts the protocol' do
972
+ expect(hosts[0][:scheme]).to eq('http')
973
+ end
974
+
975
+ it 'defaults to port 9200' do
798
976
  expect(hosts[0][:port]).to be(9200)
799
- expect(hosts[0][:path]).to eq("/foo/bar")
977
+ end
978
+
979
+ it 'extracts the path' do
980
+ expect(hosts[0][:path]).to eq('/foo/bar')
800
981
  end
801
982
  end
802
983
 
@@ -806,7 +987,7 @@ describe Elasticsearch::Transport::Client do
806
987
  ['host1', 'host2']
807
988
  end
808
989
 
809
- it 'extracts the host' do
990
+ it 'extracts the hosts' do
810
991
  expect(hosts[0][:host]).to eq('host1')
811
992
  expect(hosts[0][:protocol]).to eq('http')
812
993
  expect(hosts[0][:port]).to be(9200)
@@ -822,7 +1003,7 @@ describe Elasticsearch::Transport::Client do
822
1003
  ['host1:1000', 'host2:2000']
823
1004
  end
824
1005
 
825
- it 'extracts the host' do
1006
+ it 'extracts the hosts' do
826
1007
  expect(hosts[0][:host]).to eq('host1')
827
1008
  expect(hosts[0][:protocol]).to eq('http')
828
1009
  expect(hosts[0][:port]).to be(1000)
@@ -1242,7 +1423,7 @@ describe Elasticsearch::Transport::Client do
1242
1423
  allow(client).to receive(:perform_request) { OpenStruct.new(body: '') }
1243
1424
  expect { client.search(opaque_id: 'opaque_id') }.not_to raise_error
1244
1425
  expect(client).to have_received(:perform_request)
1245
- .with('GET', '_search', { opaque_id: 'opaque_id' }, nil, {})
1426
+ .with('GET', '_search', { opaque_id: 'opaque_id' }, nil, {})
1246
1427
  end
1247
1428
  end
1248
1429
  end
@@ -1281,7 +1462,28 @@ describe Elasticsearch::Transport::Client do
1281
1462
  allow(client).to receive(:perform_request) { OpenStruct.new(body: '') }
1282
1463
  expect { client.search(headers: headers) }.not_to raise_error
1283
1464
  expect(client).to have_received(:perform_request)
1284
- .with('GET', '_search', {}, nil, headers)
1465
+ .with('GET', '_search', {}, nil, headers)
1466
+ end
1467
+ end
1468
+
1469
+ context 'when a header is set on an endpoint request and on initialization' do
1470
+ let!(:client) do
1471
+ described_class.new(
1472
+ host: hosts,
1473
+ transport_options: { headers: instance_headers }
1474
+ )
1475
+ end
1476
+ let(:instance_headers) { { set_in_instantiation: 'header value' } }
1477
+ let(:param_headers) {{'user-agent' => 'My Ruby Tests', 'set-on-method-call' => 'header value'}}
1478
+
1479
+ it 'performs the request with the header' do
1480
+ expected_headers = client.transport.connections.connections.first.connection.headers.merge(param_headers)
1481
+
1482
+ expect_any_instance_of(Faraday::Connection)
1483
+ .to receive(:run_request)
1484
+ .with(:get, "http://#{hosts[0]}/_search", nil, expected_headers) { OpenStruct.new(body: '')}
1485
+
1486
+ client.search(headers: param_headers)
1285
1487
  end
1286
1488
  end
1287
1489
  end
@@ -1503,7 +1705,7 @@ describe Elasticsearch::Transport::Client do
1503
1705
  context 'when using the HTTPClient adapter' do
1504
1706
 
1505
1707
  let(:client) do
1506
- described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :httpclient)
1708
+ described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :httpclient, enable_meta_header: false)
1507
1709
  end
1508
1710
 
1509
1711
  it 'compresses the request and decompresses the response' do