elasticsearch-transport 7.1.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +13 -9
  3. data/{LICENSE.txt → LICENSE} +0 -0
  4. data/README.md +175 -76
  5. data/Rakefile +1 -1
  6. data/elasticsearch-transport.gemspec +42 -60
  7. data/lib/elasticsearch/transport/client.rb +154 -57
  8. data/lib/elasticsearch/transport/meta_header.rb +135 -0
  9. data/lib/elasticsearch/transport/redacted.rb +1 -1
  10. data/lib/elasticsearch/transport/transport/base.rb +93 -18
  11. data/lib/elasticsearch/transport/transport/connections/collection.rb +3 -6
  12. data/lib/elasticsearch/transport/transport/connections/connection.rb +8 -6
  13. data/lib/elasticsearch/transport/transport/connections/selector.rb +18 -6
  14. data/lib/elasticsearch/transport/transport/errors.rb +1 -1
  15. data/lib/elasticsearch/transport/transport/http/curb.rb +26 -9
  16. data/lib/elasticsearch/transport/transport/http/faraday.rb +27 -5
  17. data/lib/elasticsearch/transport/transport/http/manticore.rb +25 -10
  18. data/lib/elasticsearch/transport/transport/loggable.rb +1 -1
  19. data/lib/elasticsearch/transport/transport/response.rb +1 -2
  20. data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +1 -1
  21. data/lib/elasticsearch/transport/transport/sniffer.rb +20 -12
  22. data/lib/elasticsearch/transport/version.rb +2 -2
  23. data/lib/elasticsearch/transport.rb +1 -1
  24. data/lib/elasticsearch-transport.rb +1 -1
  25. data/spec/elasticsearch/connections/collection_spec.rb +266 -0
  26. data/spec/elasticsearch/connections/selector_spec.rb +174 -0
  27. data/spec/elasticsearch/transport/base_spec.rb +197 -13
  28. data/spec/elasticsearch/transport/client_spec.rb +945 -118
  29. data/spec/elasticsearch/transport/meta_header_spec.rb +265 -0
  30. data/spec/elasticsearch/transport/sniffer_spec.rb +1 -14
  31. data/spec/spec_helper.rb +25 -1
  32. data/test/integration/transport_test.rb +15 -2
  33. data/test/profile/client_benchmark_test.rb +1 -1
  34. data/test/test_helper.rb +1 -1
  35. data/test/unit/connection_test.rb +8 -3
  36. data/test/unit/response_test.rb +2 -2
  37. data/test/unit/serializer_test.rb +1 -1
  38. data/test/unit/transport_base_test.rb +2 -2
  39. data/test/unit/transport_curb_test.rb +2 -2
  40. data/test/unit/transport_faraday_test.rb +3 -3
  41. data/test/unit/transport_manticore_test.rb +30 -14
  42. metadata +87 -60
  43. data/test/unit/connection_collection_test.rb +0 -147
  44. data/test/unit/connection_selector_test.rb +0 -81
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -18,7 +18,6 @@
18
18
  require 'spec_helper'
19
19
 
20
20
  describe Elasticsearch::Transport::Client do
21
-
22
21
  let(:client) do
23
22
  described_class.new.tap do |_client|
24
23
  allow(_client).to receive(:__build_connections)
@@ -33,58 +32,253 @@ describe Elasticsearch::Transport::Client do
33
32
  expect(client.transport).to be_a(Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS)
34
33
  end
35
34
 
36
- it 'uses Faraday as the default transport' do
35
+ it 'preserves the Faraday default user agent header' do
37
36
  expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/Faraday/)
38
37
  end
39
38
 
39
+ it 'identifies the Ruby client in the User-Agent header' do
40
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/elasticsearch-ruby\/#{Elasticsearch::Transport::VERSION}/)
41
+ end
42
+
43
+ it 'identifies the Ruby version in the User-Agent header' do
44
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/#{RUBY_VERSION}/)
45
+ end
46
+
47
+ it 'identifies the host_os in the User-Agent header' do
48
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase}/)
49
+ end
50
+
51
+ it 'identifies the target_cpu in the User-Agent header' do
52
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/#{RbConfig::CONFIG['target_cpu']}/)
53
+ end
54
+
40
55
  it 'sets the \'Content-Type\' header to \'application/json\' by default' do
41
- expect(client.transport.options[:transport_options][:headers]['Content-Type']).to eq('application/json')
56
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
42
57
  end
43
58
 
44
59
  it 'uses localhost by default' do
45
60
  expect(client.transport.hosts[0][:host]).to eq('localhost')
46
61
  end
47
62
 
48
- describe 'adapter' do
63
+ context 'when a User-Agent header is specified as client option' do
64
+ let(:client) do
65
+ described_class.new(transport_options: { headers: { 'User-Agent' => 'testing' } })
66
+ end
49
67
 
50
- context 'when no adapter is specified' do
68
+ it 'sets the specified User-Agent header' do
69
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to eq('testing')
70
+ end
71
+ end
72
+
73
+ context 'when an encoded api_key is provided' do
74
+ let(:client) do
75
+ described_class.new(api_key: 'an_api_key')
76
+ end
77
+ let(:authorization_header) do
78
+ client.transport.connections.first.connection.headers['Authorization']
79
+ end
80
+
81
+ it 'Adds the ApiKey header to the connection' do
82
+ expect(authorization_header).to eq('ApiKey an_api_key')
83
+ end
84
+ end
85
+
86
+ context 'when an un-encoded api_key is provided' do
87
+ let(:client) do
88
+ described_class.new(api_key: { id: 'my_id', api_key: 'my_api_key' })
89
+ end
90
+ let(:authorization_header) do
91
+ client.transport.connections.first.connection.headers['Authorization']
92
+ end
93
+
94
+ it 'Adds the ApiKey header to the connection' do
95
+ expect(authorization_header).to eq("ApiKey #{Base64.strict_encode64('my_id:my_api_key')}")
96
+ end
97
+ end
98
+
99
+ context 'when basic auth and api_key are provided' do
100
+ let(:client) do
101
+ described_class.new(
102
+ api_key: { id: 'my_id', api_key: 'my_api_key' },
103
+ host: 'http://elastic:password@localhost:9200'
104
+ )
105
+ end
106
+ let(:authorization_header) do
107
+ client.transport.connections.first.connection.headers['Authorization']
108
+ end
109
+
110
+ it 'removes basic auth credentials' do
111
+ expect(authorization_header).not_to match(/^Basic/)
112
+ expect(authorization_header).to match(/^ApiKey/)
113
+ end
114
+ end
115
+
116
+ context 'when a user-agent header is specified as client option in lower-case' do
117
+
118
+ let(:client) do
119
+ described_class.new(transport_options: { headers: { 'user-agent' => 'testing' } })
120
+ end
121
+
122
+ it 'sets the specified User-Agent header' do
123
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to eq('testing')
124
+ end
125
+ end
126
+
127
+ context 'when a Content-Type header is specified as client option' do
128
+
129
+ let(:client) do
130
+ described_class.new(transport_options: { headers: { 'Content-Type' => 'testing' } })
131
+ end
132
+
133
+ it 'sets the specified Content-Type header' do
134
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('testing')
135
+ end
136
+ end
137
+
138
+ context 'when a content-type header is specified as client option in lower-case' do
139
+
140
+ let(:client) do
141
+ described_class.new(transport_options: { headers: { 'content-type' => 'testing' } })
142
+ end
143
+
144
+ it 'sets the specified Content-Type header' do
145
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('testing')
146
+ end
147
+ end
148
+
149
+ context 'when the Curb transport class is used', unless: jruby? do
150
+
151
+ let(:client) do
152
+ described_class.new(transport_class: Elasticsearch::Transport::Transport::HTTP::Curb)
153
+ end
154
+
155
+ it 'preserves the Curb default user agent header' do
156
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/Curb/)
157
+ end
51
158
 
159
+ it 'identifies the Ruby client in the User-Agent header' do
160
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/elasticsearch-ruby\/#{Elasticsearch::Transport::VERSION}/)
161
+ end
162
+
163
+ it 'identifies the Ruby version in the User-Agent header' do
164
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/#{RUBY_VERSION}/)
165
+ end
166
+
167
+ it 'identifies the host_os in the User-Agent header' do
168
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase}/)
169
+ end
170
+
171
+ it 'identifies the target_cpu in the User-Agent header' do
172
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to match(/#{RbConfig::CONFIG['target_cpu']}/)
173
+ end
174
+
175
+ it 'sets the \'Content-Type\' header to \'application/json\' by default' do
176
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
177
+ end
178
+
179
+ it 'uses localhost by default' do
180
+ expect(client.transport.hosts[0][:host]).to eq('localhost')
181
+ end
182
+
183
+ context 'when a User-Agent header is specified as a client option' do
184
+
185
+ let(:client) do
186
+ described_class.new(transport_class: Elasticsearch::Transport::Transport::HTTP::Curb,
187
+ transport_options: { headers: { 'User-Agent' => 'testing' } })
188
+ end
189
+
190
+ it 'sets the specified User-Agent header' do
191
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to eq('testing')
192
+ end
193
+ end
194
+
195
+ context 'when a user-agent header is specified as a client option as lower-case' do
196
+
197
+ let(:client) do
198
+ described_class.new(transport_class: Elasticsearch::Transport::Transport::HTTP::Curb,
199
+ transport_options: { headers: { 'user-agent' => 'testing' } })
200
+ end
201
+
202
+ it 'sets the specified User-Agent header' do
203
+ expect(client.transport.connections.first.connection.headers['User-Agent']).to eq('testing')
204
+ end
205
+ end
206
+
207
+ context 'when a Content-Type header is specified as client option' do
208
+
209
+ let(:client) do
210
+ described_class.new(transport_class: Elasticsearch::Transport::Transport::HTTP::Curb,
211
+ transport_options: { headers: { 'Content-Type' => 'testing' } })
212
+ end
213
+
214
+ it 'sets the specified Content-Type header' do
215
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('testing')
216
+ end
217
+ end
218
+
219
+ context 'when a content-type header is specified as client option in lower-case' do
220
+
221
+ let(:client) do
222
+ described_class.new(transport_class: Elasticsearch::Transport::Transport::HTTP::Curb,
223
+ transport_options: { headers: { 'content-type' => 'testing' } })
224
+ end
225
+
226
+ it 'sets the specified Content-Type header' do
227
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('testing')
228
+ end
229
+ end
230
+ end
231
+
232
+ describe 'adapter' do
233
+ context 'when no adapter is specified' do
52
234
  let(:adapter) do
53
- client.transport.connections.all.first.connection.builder.handlers
235
+ client.transport.connections.all.first.connection.builder.adapter
54
236
  end
55
237
 
56
238
  it 'uses Faraday NetHttp' do
57
- expect(adapter).to include(Faraday::Adapter::NetHttp)
239
+ expect(adapter).to eq Faraday::Adapter::NetHttp
58
240
  end
59
241
  end
60
242
 
61
- context 'when the adapter is specified' do
62
-
243
+ context 'when the adapter is patron' do
63
244
  let(:adapter) do
64
- client.transport.connections.all.first.connection.builder.handlers
245
+ client.transport.connections.all.first.connection.builder.adapter
65
246
  end
66
247
 
67
248
  let(:client) do
68
- described_class.new(adapter: :typhoeus)
249
+ described_class.new(adapter: :patron, enable_meta_header: false)
69
250
  end
70
251
 
71
252
  it 'uses Faraday with the adapter' do
72
- expect(adapter).to include(Faraday::Adapter::Typhoeus)
253
+ expect(adapter).to eq Faraday::Adapter::Patron
73
254
  end
74
255
  end
75
256
 
76
- context 'when the adapter is specified as a string key' do
257
+ context 'when the adapter is typhoeus' do
258
+ let(:adapter) do
259
+ client.transport.connections.all.first.connection.builder.adapter
260
+ end
77
261
 
262
+ let(:client) do
263
+ described_class.new(adapter: :typhoeus, enable_meta_header: false)
264
+ end
265
+
266
+ it 'uses Faraday with the adapter' do
267
+ expect(adapter).to eq Faraday::Adapter::Typhoeus
268
+ end
269
+ end unless jruby?
270
+
271
+ context 'when the adapter is specified as a string key' do
78
272
  let(:adapter) do
79
- client.transport.connections.all.first.connection.builder.handlers
273
+ client.transport.connections.all.first.connection.builder.adapter
80
274
  end
81
275
 
82
276
  let(:client) do
83
- described_class.new('adapter' => :typhoeus)
277
+ described_class.new(adapter: :patron, enable_meta_header: false)
84
278
  end
85
279
 
86
280
  it 'uses Faraday with the adapter' do
87
- expect(adapter).to include(Faraday::Adapter::Typhoeus)
281
+ expect(adapter).to eq Faraday::Adapter::Patron
88
282
  end
89
283
  end
90
284
 
@@ -96,11 +290,11 @@ describe Elasticsearch::Transport::Client do
96
290
  end
97
291
 
98
292
  let(:adapter) do
99
- client.transport.connections.all.first.connection.builder.handlers
293
+ client.transport.connections.all.first.connection.builder.adapter
100
294
  end
101
295
 
102
296
  it 'uses the detected adapter' do
103
- expect(adapter).to include(Faraday::Adapter::Patron)
297
+ expect(adapter).to eq Faraday::Adapter::Patron
104
298
  end
105
299
  end
106
300
 
@@ -108,17 +302,21 @@ describe Elasticsearch::Transport::Client do
108
302
 
109
303
  let(:client) do
110
304
  described_class.new do |faraday|
111
- faraday.adapter :typhoeus
305
+ faraday.adapter :patron
112
306
  faraday.response :logger
113
307
  end
114
308
  end
115
309
 
310
+ let(:adapter) do
311
+ client.transport.connections.all.first.connection.builder.adapter
312
+ end
313
+
116
314
  let(:handlers) do
117
315
  client.transport.connections.all.first.connection.builder.handlers
118
316
  end
119
317
 
120
318
  it 'sets the adapter' do
121
- expect(handlers).to include(Faraday::Adapter::Typhoeus)
319
+ expect(adapter).to eq Faraday::Adapter::Patron
122
320
  end
123
321
 
124
322
  it 'sets the logger' do
@@ -127,114 +325,400 @@ describe Elasticsearch::Transport::Client do
127
325
  end
128
326
  end
129
327
 
130
- shared_examples_for 'a client that extracts hosts' do
328
+ context 'when cloud credentials are provided' do
329
+
330
+ let(:client) do
331
+ described_class.new(
332
+ cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
333
+ user: 'elastic',
334
+ password: 'changeme'
335
+ )
336
+ end
337
+
338
+ let(:hosts) do
339
+ client.transport.hosts
340
+ end
131
341
 
132
- context 'when the hosts are a String' do
342
+ it 'extracts the cloud credentials' do
343
+ expect(hosts[0][:host]).to eq('abcd.localhost')
344
+ expect(hosts[0][:protocol]).to eq('https')
345
+ expect(hosts[0][:user]).to eq('elastic')
346
+ expect(hosts[0][:password]).to eq('changeme')
347
+ expect(hosts[0][:port]).to eq(443)
348
+ end
133
349
 
134
- let(:host) do
135
- 'myhost'
350
+ it 'creates the correct full url' do
351
+ expect(
352
+ client.transport.__full_url(client.transport.hosts[0])
353
+ ).to eq('https://elastic:changeme@abcd.localhost:443')
354
+ end
355
+
356
+ context 'when a port is specified' do
357
+
358
+ let(:client) do
359
+ described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port: 9250)
136
360
  end
137
361
 
138
- it 'extracts the host' do
139
- expect(hosts[0][:host]).to eq('myhost')
140
- expect(hosts[0][:protocol]).to eq('http')
141
- expect(hosts[0][:port]).to be(9200)
362
+ it 'sets the specified port along with the cloud credentials' do
363
+ expect(hosts[0][:host]).to eq('abcd.localhost')
364
+ expect(hosts[0][:protocol]).to eq('https')
365
+ expect(hosts[0][:user]).to eq('elastic')
366
+ expect(hosts[0][:password]).to eq('changeme')
367
+ expect(hosts[0][:port]).to eq(9250)
142
368
  end
143
369
 
144
- context 'when IPv6 format is used' do
370
+ it 'creates the correct full url' do
371
+ expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:9250')
372
+ end
373
+ end
145
374
 
146
- around do |example|
147
- original_setting = Faraday.ignore_env_proxy
148
- Faraday.ignore_env_proxy = true
149
- example.run
150
- Faraday.ignore_env_proxy = original_setting
151
- end
375
+ context 'when the cluster has alternate names' do
152
376
 
153
- let(:host) do
154
- 'https://[2090:db8:85a3:9811::1f]:8080'
155
- end
377
+ let(:client) do
378
+ described_class.new(
379
+ cloud_id: 'myCluster:bG9jYWxob3N0JGFiY2QkZWZnaA==',
380
+ user: 'elasticfantastic',
381
+ password: 'tobechanged'
382
+ )
383
+ end
156
384
 
157
- it 'extracts the host' do
158
- expect(hosts[0][:host]).to eq('[2090:db8:85a3:9811::1f]')
159
- expect(hosts[0][:scheme]).to eq('https')
160
- expect(hosts[0][:port]).to be(8080)
161
- end
385
+ let(:hosts) do
386
+ client.transport.hosts
387
+ end
162
388
 
163
- it 'creates the correct full url' do
164
- expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://[2090:db8:85a3:9811::1f]:8080')
165
- end
389
+ it 'extracts the cloud credentials' do
390
+ expect(hosts[0][:host]).to eq('abcd.localhost')
391
+ expect(hosts[0][:protocol]).to eq('https')
392
+ expect(hosts[0][:user]).to eq('elasticfantastic')
393
+ expect(hosts[0][:password]).to eq('tobechanged')
394
+ expect(hosts[0][:port]).to eq(443)
166
395
  end
167
396
 
168
- context 'when a path is specified' do
397
+ it 'creates the correct full url' do
398
+ expect(
399
+ client.transport.__full_url(client.transport.hosts[0])
400
+ ).to eq('https://elasticfantastic:tobechanged@abcd.localhost:443')
401
+ end
402
+ end
169
403
 
170
- let(:host) do
171
- 'https://myhost:8080/api'
172
- end
404
+ context 'when decoded cloud id has a trailing dollar sign' do
405
+ let(:client) do
406
+ described_class.new(
407
+ cloud_id: 'a_cluster:bG9jYWxob3N0JGFiY2Qk',
408
+ user: 'elasticfantastic',
409
+ password: 'changeme'
410
+ )
411
+ end
173
412
 
174
- it 'extracts the host' do
175
- expect(hosts[0][:host]).to eq('myhost')
176
- expect(hosts[0][:scheme]).to eq('https')
177
- expect(hosts[0][:path]).to eq('/api')
178
- expect(hosts[0][:port]).to be(8080)
179
- end
413
+ let(:hosts) do
414
+ client.transport.hosts
180
415
  end
181
416
 
182
- context 'when a scheme is specified' do
417
+ it 'extracts the cloud credentials' do
418
+ expect(hosts[0][:host]).to eq('abcd.localhost')
419
+ expect(hosts[0][:protocol]).to eq('https')
420
+ expect(hosts[0][:user]).to eq('elasticfantastic')
421
+ expect(hosts[0][:password]).to eq('changeme')
422
+ expect(hosts[0][:port]).to eq(443)
423
+ end
183
424
 
184
- let(:host) do
185
- 'https://myhost:8080'
186
- end
425
+ it 'creates the correct full url' do
426
+ expect(
427
+ client.transport.__full_url(client.transport.hosts[0])
428
+ ).to eq('https://elasticfantastic:changeme@abcd.localhost:443')
429
+ end
430
+ end
187
431
 
188
- it 'extracts the host' do
189
- expect(hosts[0][:host]).to eq('myhost')
190
- expect(hosts[0][:scheme]).to eq('https')
191
- expect(hosts[0][:port]).to be(8080)
192
- end
432
+ context 'when the cloud host provides a port' do
433
+ let(:client) do
434
+ described_class.new(
435
+ cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk',
436
+ user: 'elastic',
437
+ password: 'changeme'
438
+ )
193
439
  end
194
440
 
195
- context 'when credentials are specified' do
441
+ let(:hosts) do
442
+ client.transport.hosts
443
+ end
196
444
 
197
- let(:host) do
198
- 'http://USERNAME:PASSWORD@myhost:8080'
445
+ it 'creates the correct full url' do
446
+ expect(hosts[0][:host]).to eq('elastic_id.elastic_server')
447
+ expect(hosts[0][:protocol]).to eq('https')
448
+ expect(hosts[0][:user]).to eq('elastic')
449
+ expect(hosts[0][:password]).to eq('changeme')
450
+ expect(hosts[0][:port]).to eq(9243)
451
+ end
452
+ end
453
+
454
+ context 'when the cloud host provides a port and the port is also specified' do
455
+ let(:client) do
456
+ described_class.new(
457
+ cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk',
458
+ user: 'elastic',
459
+ password: 'changeme',
460
+ port: 9200
461
+ )
462
+ end
463
+
464
+ let(:hosts) do
465
+ client.transport.hosts
466
+ end
467
+
468
+ it 'creates the correct full url' do
469
+ expect(hosts[0][:host]).to eq('elastic_id.elastic_server')
470
+ expect(hosts[0][:protocol]).to eq('https')
471
+ expect(hosts[0][:user]).to eq('elastic')
472
+ expect(hosts[0][:password]).to eq('changeme')
473
+ expect(hosts[0][:port]).to eq(9243)
474
+ end
475
+ end
476
+ end
477
+
478
+ shared_examples_for 'a client that extracts hosts' do
479
+
480
+ context 'when the host is a String' do
481
+
482
+ context 'when there is a protocol specified' do
483
+
484
+ context 'when credentials are specified \'http://USERNAME:PASSWORD@myhost:8080\'' do
485
+
486
+ let(:host) do
487
+ 'http://USERNAME:PASSWORD@myhost:8080'
488
+ end
489
+
490
+ it 'extracts the credentials' do
491
+ expect(hosts[0][:user]).to eq('USERNAME')
492
+ expect(hosts[0][:password]).to eq('PASSWORD')
493
+ end
494
+
495
+ it 'extracts the host' do
496
+ expect(hosts[0][:host]).to eq('myhost')
497
+ end
498
+
499
+ it 'extracts the port' do
500
+ expect(hosts[0][:port]).to be(8080)
501
+ end
199
502
  end
200
503
 
201
- it 'extracts the host' do
202
- expect(hosts[0][:host]).to eq('myhost')
203
- expect(hosts[0][:scheme]).to eq('http')
204
- expect(hosts[0][:user]).to eq('USERNAME')
205
- expect(hosts[0][:password]).to eq('PASSWORD')
206
- expect(hosts[0][:port]).to be(8080)
504
+ context 'when there is a trailing slash \'http://myhost/\'' do
505
+
506
+ let(:host) do
507
+ 'http://myhost/'
508
+ end
509
+
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
515
+
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
207
523
  end
208
- end
209
524
 
210
- context 'when there is a trailing slash' do
525
+ context 'when there is a trailing slash with a path \'http://myhost/foo/bar/\'' do
211
526
 
212
- let(:host) do
213
- 'http://myhost/'
527
+ let(:host) do
528
+ 'http://myhost/foo/bar/'
529
+ end
530
+
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
214
536
  end
215
537
 
216
- it 'extracts the host' do
217
- expect(hosts[0][:host]).to eq('myhost')
218
- expect(hosts[0][:scheme]).to eq('http')
219
- expect(hosts[0][:path]).to eq('')
538
+ context 'when the protocol is http' do
539
+
540
+ context 'when there is no port specified \'http://myhost\'' do
541
+
542
+ let(:host) do
543
+ 'http://myhost'
544
+ end
545
+
546
+ it 'extracts the host' do
547
+ expect(hosts[0][:host]).to eq('myhost')
548
+ end
549
+
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
607
+ end
608
+
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
220
701
  end
221
702
  end
222
703
 
223
- context 'when there is a trailing slash with a path' do
704
+ context 'when no protocol is specified \'myhost\'' do
224
705
 
225
706
  let(:host) do
226
- 'http://myhost/foo/bar/'
707
+ 'myhost'
227
708
  end
228
709
 
229
- it 'extracts the host' do
710
+ it 'defaults to http' do
230
711
  expect(hosts[0][:host]).to eq('myhost')
231
- expect(hosts[0][:scheme]).to eq('http')
232
- 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)
233
717
  end
234
718
  end
235
719
  end
236
720
 
237
- context 'when the hosts are a Hash' do
721
+ context 'when the host is a Hash' do
238
722
 
239
723
  let(:host) do
240
724
  { :host => 'myhost', :scheme => 'https' }
@@ -242,7 +726,13 @@ describe Elasticsearch::Transport::Client do
242
726
 
243
727
  it 'extracts the host' do
244
728
  expect(hosts[0][:host]).to eq('myhost')
245
- 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
246
736
  expect(hosts[0][:port]).to be(9200)
247
737
  end
248
738
 
@@ -301,7 +791,13 @@ describe Elasticsearch::Transport::Client do
301
791
 
302
792
  it 'extracts the host' do
303
793
  expect(hosts[0][:host]).to eq('myhost')
794
+ end
795
+
796
+ it 'extracts the protocol' do
304
797
  expect(hosts[0][:scheme]).to eq('https')
798
+ end
799
+
800
+ it 'converts the port to an integer' do
305
801
  expect(hosts[0][:port]).to be(443)
306
802
  end
307
803
  end
@@ -314,7 +810,13 @@ describe Elasticsearch::Transport::Client do
314
810
 
315
811
  it 'extracts the host' do
316
812
  expect(hosts[0][:host]).to eq('myhost')
813
+ end
814
+
815
+ it 'extracts the protocol' do
317
816
  expect(hosts[0][:scheme]).to eq('https')
817
+ end
818
+
819
+ it 'extracts port as an integer' do
318
820
  expect(hosts[0][:port]).to be(443)
319
821
  end
320
822
  end
@@ -328,7 +830,13 @@ describe Elasticsearch::Transport::Client do
328
830
 
329
831
  it 'extracts the host' do
330
832
  expect(hosts[0][:host]).to eq('myhost')
833
+ end
834
+
835
+ it 'extracts the protocol' do
331
836
  expect(hosts[0][:scheme]).to eq('https')
837
+ end
838
+
839
+ it 'converts the port to an integer' do
332
840
  expect(hosts[0][:port]).to be(9200)
333
841
  end
334
842
 
@@ -340,7 +848,13 @@ describe Elasticsearch::Transport::Client do
340
848
 
341
849
  it 'extracts the host' do
342
850
  expect(hosts[0][:host]).to eq('myhost')
851
+ end
852
+
853
+ it 'extracts the protocol' do
343
854
  expect(hosts[0][:scheme]).to eq('https')
855
+ end
856
+
857
+ it 'converts the port to an integer' do
344
858
  expect(hosts[0][:port]).to be(443)
345
859
  end
346
860
  end
@@ -353,7 +867,13 @@ describe Elasticsearch::Transport::Client do
353
867
 
354
868
  it 'extracts the host' do
355
869
  expect(hosts[0][:host]).to eq('myhost')
870
+ end
871
+
872
+ it 'extracts the protocol' do
356
873
  expect(hosts[0][:scheme]).to eq('https')
874
+ end
875
+
876
+ it 'extracts port as an integer' do
357
877
  expect(hosts[0][:port]).to be(443)
358
878
  end
359
879
  end
@@ -369,7 +889,13 @@ describe Elasticsearch::Transport::Client do
369
889
 
370
890
  it 'extracts the host' do
371
891
  expect(hosts[0][:host]).to eq('myhost')
892
+ end
893
+
894
+ it 'extracts the protocol' do
372
895
  expect(hosts[0][:protocol]).to eq('http')
896
+ end
897
+
898
+ it 'defaults to port 9200' do
373
899
  expect(hosts[0][:port]).to be(9200)
374
900
  end
375
901
  end
@@ -382,20 +908,13 @@ describe Elasticsearch::Transport::Client do
382
908
 
383
909
  it 'extracts the host' do
384
910
  expect(hosts[0][:host]).to eq('myhost')
385
- expect(hosts[0][:protocol]).to eq('http')
386
- expect(hosts[0][:port]).to be(9200)
387
911
  end
388
- end
389
-
390
- context 'when there is one host with a protocol and no port' do
391
912
 
392
- let(:host) do
393
- ['http://myhost']
913
+ it 'extracts the protocol' do
914
+ expect(hosts[0][:scheme]).to eq('http')
394
915
  end
395
916
 
396
- it 'extracts the host' do
397
- expect(hosts[0][:host]).to eq('myhost')
398
- expect(hosts[0][:protocol]).to eq('http')
917
+ it 'defaults to port 9200' do
399
918
  expect(hosts[0][:port]).to be(9200)
400
919
  end
401
920
  end
@@ -420,7 +939,7 @@ describe Elasticsearch::Transport::Client do
420
939
  end
421
940
  end
422
941
 
423
- 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
424
943
 
425
944
  let(:host) do
426
945
  ['https://myhost']
@@ -428,12 +947,18 @@ describe Elasticsearch::Transport::Client do
428
947
 
429
948
  it 'extracts the host' do
430
949
  expect(hosts[0][:host]).to eq('myhost')
431
- expect(hosts[0][:protocol]).to eq('https')
432
- 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)
433
958
  end
434
959
  end
435
960
 
436
- 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
437
962
 
438
963
  let(:host) do
439
964
  ['http://myhost/foo/bar']
@@ -441,9 +966,18 @@ describe Elasticsearch::Transport::Client do
441
966
 
442
967
  it 'extracts the host' do
443
968
  expect(hosts[0][:host]).to eq('myhost')
444
- 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
445
976
  expect(hosts[0][:port]).to be(9200)
446
- 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')
447
981
  end
448
982
  end
449
983
 
@@ -453,7 +987,7 @@ describe Elasticsearch::Transport::Client do
453
987
  ['host1', 'host2']
454
988
  end
455
989
 
456
- it 'extracts the host' do
990
+ it 'extracts the hosts' do
457
991
  expect(hosts[0][:host]).to eq('host1')
458
992
  expect(hosts[0][:protocol]).to eq('http')
459
993
  expect(hosts[0][:port]).to be(9200)
@@ -469,7 +1003,7 @@ describe Elasticsearch::Transport::Client do
469
1003
  ['host1:1000', 'host2:2000']
470
1004
  end
471
1005
 
472
- it 'extracts the host' do
1006
+ it 'extracts the hosts' do
473
1007
  expect(hosts[0][:host]).to eq('host1')
474
1008
  expect(hosts[0][:protocol]).to eq('http')
475
1009
  expect(hosts[0][:port]).to be(1000)
@@ -859,10 +1393,142 @@ describe Elasticsearch::Transport::Client do
859
1393
  expect(request).to be(true)
860
1394
  end
861
1395
  end
1396
+
1397
+ context 'when x-opaque-id is set' do
1398
+ let(:client) { described_class.new(host: hosts) }
1399
+
1400
+ it 'uses x-opaque-id on a request' do
1401
+ expect(client.perform_request('GET', '/', { opaque_id: '12345' }).headers['x-opaque-id']).to eq('12345')
1402
+ end
1403
+ end
1404
+
1405
+ context 'when an x-opaque-id prefix is set on initialization' do
1406
+ let(:prefix) { 'elastic_cloud' }
1407
+ let(:client) do
1408
+ described_class.new(host: hosts, opaque_id_prefix: prefix)
1409
+ end
1410
+
1411
+ it 'uses x-opaque-id on a request' do
1412
+ expect(client.perform_request('GET', '/', { opaque_id: '12345' }).headers['x-opaque-id']).to eq("#{prefix}12345")
1413
+ end
1414
+
1415
+ context 'when using an API call' do
1416
+ let(:client) { described_class.new(host: hosts) }
1417
+
1418
+ it 'doesnae raise an ArgumentError' do
1419
+ expect { client.search(opaque_id: 'no_error') }.not_to raise_error
1420
+ end
1421
+
1422
+ it 'uses X-Opaque-Id in the header' do
1423
+ allow(client).to receive(:perform_request) { OpenStruct.new(body: '') }
1424
+ expect { client.search(opaque_id: 'opaque_id') }.not_to raise_error
1425
+ expect(client).to have_received(:perform_request)
1426
+ .with('GET', '_search', { opaque_id: 'opaque_id' }, nil, {})
1427
+ end
1428
+ end
1429
+ end
1430
+
1431
+ context 'when using the API Compatibility Header' do
1432
+ it 'sets the API compatibility headers' do
1433
+ ENV['ELASTIC_CLIENT_APIVERSIONING'] = 'true'
1434
+ client = described_class.new(host: hosts)
1435
+ headers = client.transport.connections.first.connection.headers
1436
+
1437
+ expect(headers['Content-Type']).to eq('application/vnd.elasticsearch+json; compatible-with=7')
1438
+ expect(headers['Accept']).to eq('application/vnd.elasticsearch+json;compatible-with=7')
1439
+
1440
+ response = client.perform_request('GET', '/')
1441
+ expect(response.headers['content-type']).to eq('application/json; charset=UTF-8')
1442
+
1443
+ ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
1444
+ end
1445
+
1446
+ it 'does not use API compatibility headers' do
1447
+ val = ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
1448
+ client = described_class.new(host: hosts)
1449
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
1450
+ ENV['ELASTIC_CLIENT_APIVERSIONING'] = val
1451
+ end
1452
+
1453
+ it 'does not use API compatibility headers when it is set to unsupported values' do
1454
+ val = ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
1455
+
1456
+ ENV['ELASTIC_CLIENT_APIVERSIONING'] = 'test'
1457
+ client = described_class.new(host: hosts)
1458
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
1459
+
1460
+ ENV['ELASTIC_CLIENT_APIVERSIONING'] = 'false'
1461
+ client = described_class.new(host: hosts)
1462
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
1463
+
1464
+ ENV['ELASTIC_CLIENT_APIVERSIONING'] = '3'
1465
+ client = described_class.new(host: hosts)
1466
+ expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
1467
+ ENV['ELASTIC_CLIENT_APIVERSIONING'] = val
1468
+ end
1469
+ end
1470
+
1471
+ context 'when Elasticsearch response includes a warning header' do
1472
+ let(:client) do
1473
+ Elasticsearch::Transport::Client.new(hosts: hosts)
1474
+ end
1475
+
1476
+ let(:warning) { 'Elasticsearch warning: "deprecation warning"' }
1477
+
1478
+ it 'prints a warning' do
1479
+ allow_any_instance_of(Elasticsearch::Transport::Transport::Response).to receive(:headers) do
1480
+ { 'warning' => warning }
1481
+ end
1482
+
1483
+ begin
1484
+ stderr = $stderr
1485
+ fake_stderr = StringIO.new
1486
+ $stderr = fake_stderr
1487
+
1488
+ client.perform_request('GET', '/')
1489
+ fake_stderr.rewind
1490
+ expect(fake_stderr.string).to eq("warning: #{warning}\n")
1491
+ ensure
1492
+ $stderr = stderr
1493
+ end
1494
+ end
1495
+ end
1496
+
1497
+ context 'when a header is set on an endpoint request' do
1498
+ let(:client) { described_class.new(host: hosts) }
1499
+ let(:headers) { { 'user-agent' => 'my ruby app' } }
1500
+
1501
+ it 'performs the request with the header' do
1502
+ allow(client).to receive(:perform_request) { OpenStruct.new(body: '') }
1503
+ expect { client.search(headers: headers) }.not_to raise_error
1504
+ expect(client).to have_received(:perform_request)
1505
+ .with('GET', '_search', {}, nil, headers)
1506
+ end
1507
+ end
1508
+
1509
+ context 'when a header is set on an endpoint request and on initialization' do
1510
+ let!(:client) do
1511
+ described_class.new(
1512
+ host: hosts,
1513
+ transport_options: { headers: instance_headers }
1514
+ )
1515
+ end
1516
+ let(:instance_headers) { { set_in_instantiation: 'header value' } }
1517
+ let(:param_headers) {{'user-agent' => 'My Ruby Tests', 'set-on-method-call' => 'header value'}}
1518
+
1519
+ it 'performs the request with the header' do
1520
+ expected_headers = client.transport.connections.connections.first.connection.headers.merge(param_headers)
1521
+
1522
+ expect_any_instance_of(Faraday::Connection)
1523
+ .to receive(:run_request)
1524
+ .with(:get, "http://#{hosts[0]}/_search", nil, expected_headers) { OpenStruct.new(body: '')}
1525
+
1526
+ client.search(headers: param_headers)
1527
+ end
1528
+ end
862
1529
  end
863
1530
 
864
1531
  context 'when the client connects to Elasticsearch' do
865
-
866
1532
  let(:logger) do
867
1533
  Logger.new(STDERR).tap do |logger|
868
1534
  logger.formatter = proc do |severity, datetime, progname, msg|
@@ -940,15 +1606,14 @@ describe Elasticsearch::Transport::Client do
940
1606
  end
941
1607
 
942
1608
  context 'when the Faraday adapter is set in the block' do
943
-
944
1609
  let(:client) do
945
1610
  Elasticsearch::Client.new(host: ELASTICSEARCH_HOSTS.first, logger: logger) do |client|
946
1611
  client.adapter(:net_http_persistent)
947
1612
  end
948
1613
  end
949
1614
 
950
- let(:connection_handler) do
951
- client.transport.connections.first.connection.builder.handlers.first
1615
+ let(:handler_name) do
1616
+ client.transport.connections.first.connection.builder.adapter.name
952
1617
  end
953
1618
 
954
1619
  let(:response) do
@@ -956,7 +1621,7 @@ describe Elasticsearch::Transport::Client do
956
1621
  end
957
1622
 
958
1623
  it 'sets the adapter' do
959
- expect(connection_handler.name).to eq('Faraday::Adapter::NetHttpPersistent')
1624
+ expect(handler_name).to eq('Faraday::Adapter::NetHttpPersistent')
960
1625
  end
961
1626
 
962
1627
  it 'uses the adapter to connect' do
@@ -1006,7 +1671,7 @@ describe Elasticsearch::Transport::Client do
1006
1671
  expect(client.perform_request('GET', '_nodes/_local'))
1007
1672
  expect {
1008
1673
  client.perform_request('GET', '_nodes/_local')
1009
- }.to raise_exception(Faraday::Error::ConnectionFailed)
1674
+ }.to raise_exception(Faraday::ConnectionFailed)
1010
1675
  end
1011
1676
  end
1012
1677
 
@@ -1053,6 +1718,141 @@ describe Elasticsearch::Transport::Client do
1053
1718
  }.to raise_exception(Elasticsearch::Transport::Transport::Errors::BadRequest)
1054
1719
  end
1055
1720
  end
1721
+
1722
+ context 'when the \'compression\' option is set to true' do
1723
+
1724
+ context 'when using Faraday as the transport' do
1725
+
1726
+ context 'when using the Net::HTTP adapter' do
1727
+
1728
+ let(:client) do
1729
+ described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :net_http)
1730
+ end
1731
+
1732
+ it 'compresses the request and decompresses the response' do
1733
+ expect(client.perform_request('GET', '/').body).to be_a(Hash)
1734
+ end
1735
+
1736
+ it 'sets the Accept-Encoding header' do
1737
+ expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
1738
+ end
1739
+
1740
+ it 'preserves the other headers' do
1741
+ expect(client.transport.connections[0].connection.headers['User-Agent'])
1742
+ end
1743
+ end
1744
+
1745
+ context 'when using the HTTPClient adapter' do
1746
+
1747
+ let(:client) do
1748
+ described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :httpclient, enable_meta_header: false)
1749
+ end
1750
+
1751
+ it 'compresses the request and decompresses the response' do
1752
+ expect(client.perform_request('GET', '/').body).to be_a(Hash)
1753
+ end
1754
+
1755
+ it 'sets the Accept-Encoding header' do
1756
+ expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
1757
+ end
1758
+
1759
+ it 'preserves the other headers' do
1760
+ expect(client.transport.connections[0].connection.headers['User-Agent'])
1761
+ end
1762
+ end
1763
+
1764
+ context 'when using the Patron adapter', unless: jruby? do
1765
+
1766
+ let(:client) do
1767
+ described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :patron)
1768
+ end
1769
+
1770
+ it 'compresses the request and decompresses the response' do
1771
+ expect(client.perform_request('GET', '/').body).to be_a(Hash)
1772
+ end
1773
+
1774
+ it 'sets the Accept-Encoding header' do
1775
+ expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
1776
+ end
1777
+
1778
+ it 'preserves the other headers' do
1779
+ expect(client.transport.connections[0].connection.headers['User-Agent'])
1780
+ end
1781
+ end
1782
+
1783
+ context 'when using the Net::HTTP::Persistent adapter' do
1784
+
1785
+ let(:client) do
1786
+ described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :net_http_persistent)
1787
+ end
1788
+
1789
+ it 'compresses the request and decompresses the response' do
1790
+ expect(client.perform_request('GET', '/').body).to be_a(Hash)
1791
+ end
1792
+
1793
+ it 'sets the Accept-Encoding header' do
1794
+ expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
1795
+ end
1796
+
1797
+ it 'preserves the other headers' do
1798
+ expect(client.transport.connections[0].connection.headers['User-Agent'])
1799
+ end
1800
+ end
1801
+
1802
+ context 'when using the Typhoeus adapter' do
1803
+
1804
+ let(:client) do
1805
+ described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :typhoeus)
1806
+ end
1807
+
1808
+ it 'compresses the request and decompresses the response' do
1809
+ expect(client.perform_request('GET', '/').body).to be_a(Hash)
1810
+ end
1811
+
1812
+ it 'sets the Accept-Encoding header' do
1813
+ expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
1814
+ end
1815
+
1816
+ it 'preserves the other headers' do
1817
+ expect(client.transport.connections[0].connection.headers['User-Agent'])
1818
+ end
1819
+ end unless jruby?
1820
+ end
1821
+ end
1822
+
1823
+ context 'when using Curb as the transport', unless: jruby? do
1824
+
1825
+ let(:client) do
1826
+ described_class.new(hosts: ELASTICSEARCH_HOSTS,
1827
+ compression: true,
1828
+ transport_class: Elasticsearch::Transport::Transport::HTTP::Curb)
1829
+ end
1830
+
1831
+ it 'compresses the request and decompresses the response' do
1832
+ expect(client.perform_request('GET', '/').body).to be_a(Hash)
1833
+ end
1834
+
1835
+ it 'sets the Accept-Encoding header' do
1836
+ expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
1837
+ end
1838
+
1839
+ it 'preserves the other headers' do
1840
+ expect(client.transport.connections[0].connection.headers['User-Agent'])
1841
+ end
1842
+ end
1843
+
1844
+ context 'when using Manticore as the transport', if: jruby? do
1845
+
1846
+ let(:client) do
1847
+ described_class.new(hosts: ELASTICSEARCH_HOSTS,
1848
+ compression: true,
1849
+ transport_class: Elasticsearch::Transport::Transport::HTTP::Manticore)
1850
+ end
1851
+
1852
+ it 'compresses the request and decompresses the response' do
1853
+ expect(client.perform_request('GET', '/').body).to be_a(Hash)
1854
+ end
1855
+ end
1056
1856
  end
1057
1857
 
1058
1858
  describe '#perform_request' do
@@ -1064,7 +1864,7 @@ describe Elasticsearch::Transport::Client do
1064
1864
  client.perform_request('DELETE', 'myindex') rescue
1065
1865
  client.perform_request('PUT', 'myindex', {}, { settings: { number_of_shards: 2, number_of_replicas: 0 } })
1066
1866
  client.perform_request('PUT', 'myindex/mydoc/1', { routing: 'XYZ', timeout: '1s' }, { foo: 'bar' })
1067
- client.perform_request('GET', '_cluster/health?wait_for_status=green', {})
1867
+ client.perform_request('GET', '_cluster/health?wait_for_status=green&timeout=2s', {})
1068
1868
  end
1069
1869
 
1070
1870
  let(:response) do
@@ -1155,12 +1955,39 @@ describe Elasticsearch::Transport::Client do
1155
1955
  { adapter: :patron }
1156
1956
  end
1157
1957
 
1158
- let(:connection_handler) do
1159
- client.transport.connections.first.connection.builder.handlers.first
1958
+ let(:adapter) do
1959
+ client.transport.connections.first.connection.builder.adapter
1960
+ end
1961
+
1962
+ it 'uses the patron connection handler' do
1963
+ expect(adapter).to eq('Faraday::Adapter::Patron')
1964
+ end
1965
+
1966
+ it 'keeps connections open' do
1967
+ response = client.perform_request('GET', '_nodes/stats/http')
1968
+ connections_before = response.body['nodes'].values.find { |n| n['name'] == node_names.first }['http']['total_opened']
1969
+ client.transport.reload_connections!
1970
+ response = client.perform_request('GET', '_nodes/stats/http')
1971
+ connections_after = response.body['nodes'].values.find { |n| n['name'] == node_names.first }['http']['total_opened']
1972
+ expect(connections_after).to be >= (connections_before)
1973
+ end
1974
+ end
1975
+
1976
+ context 'when typhoeus is used as an adapter', unless: jruby? do
1977
+ before do
1978
+ require 'typhoeus'
1979
+ end
1980
+
1981
+ let(:options) do
1982
+ { adapter: :typhoeus }
1983
+ end
1984
+
1985
+ let(:adapter) do
1986
+ client.transport.connections.first.connection.builder.adapter
1160
1987
  end
1161
1988
 
1162
1989
  it 'uses the patron connection handler' do
1163
- expect(connection_handler).to eq('Faraday::Adapter::Patron')
1990
+ expect(adapter).to eq('Faraday::Adapter::Typhoeus')
1164
1991
  end
1165
1992
 
1166
1993
  it 'keeps connections open' do