elasticsearch-transport 7.5.0 → 7.17.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +30 -13
- data/Gemfile-faraday1.gemfile +47 -0
- data/README.md +159 -64
- data/Rakefile +63 -13
- data/elasticsearch-transport.gemspec +55 -63
- data/lib/elasticsearch/transport/client.rb +183 -58
- data/lib/elasticsearch/transport/meta_header.rb +135 -0
- data/lib/elasticsearch/transport/redacted.rb +16 -3
- data/lib/elasticsearch/transport/transport/base.rb +69 -30
- data/lib/elasticsearch/transport/transport/connections/collection.rb +18 -8
- data/lib/elasticsearch/transport/transport/connections/connection.rb +25 -9
- data/lib/elasticsearch/transport/transport/connections/selector.rb +16 -3
- data/lib/elasticsearch/transport/transport/errors.rb +17 -3
- data/lib/elasticsearch/transport/transport/http/curb.rb +60 -35
- data/lib/elasticsearch/transport/transport/http/faraday.rb +32 -9
- data/lib/elasticsearch/transport/transport/http/manticore.rb +57 -32
- data/lib/elasticsearch/transport/transport/loggable.rb +16 -3
- data/lib/elasticsearch/transport/transport/response.rb +17 -5
- data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +16 -3
- data/lib/elasticsearch/transport/transport/sniffer.rb +35 -15
- data/lib/elasticsearch/transport/version.rb +17 -4
- data/lib/elasticsearch/transport.rb +35 -33
- data/lib/elasticsearch-transport.rb +16 -3
- data/spec/elasticsearch/connections/collection_spec.rb +28 -3
- data/spec/elasticsearch/connections/selector_spec.rb +16 -3
- data/spec/elasticsearch/transport/base_spec.rb +106 -43
- data/spec/elasticsearch/transport/client_spec.rb +734 -164
- data/spec/elasticsearch/transport/http/curb_spec.rb +126 -0
- data/spec/elasticsearch/transport/http/faraday_spec.rb +141 -0
- data/spec/elasticsearch/transport/http/manticore_spec.rb +161 -0
- data/spec/elasticsearch/transport/meta_header_spec.rb +301 -0
- data/spec/elasticsearch/transport/sniffer_spec.rb +16 -16
- data/spec/spec_helper.rb +32 -6
- data/test/integration/jruby_test.rb +43 -0
- data/test/integration/transport_test.rb +109 -46
- data/test/profile/client_benchmark_test.rb +16 -3
- data/test/test_helper.rb +26 -25
- data/test/unit/adapters_test.rb +88 -0
- data/test/unit/connection_test.rb +23 -5
- data/test/unit/response_test.rb +18 -5
- data/test/unit/serializer_test.rb +16 -3
- data/test/unit/transport_base_test.rb +33 -11
- data/test/unit/transport_curb_test.rb +16 -4
- data/test/unit/transport_faraday_test.rb +18 -5
- data/test/unit/transport_manticore_test.rb +258 -158
- metadata +65 -89
@@ -1,21 +1,29 @@
|
|
1
|
-
# Licensed to Elasticsearch B.V under one or more
|
2
|
-
#
|
3
|
-
#
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
4
17
|
|
5
18
|
require 'spec_helper'
|
6
19
|
|
7
20
|
describe Elasticsearch::Transport::Client do
|
8
|
-
|
9
21
|
let(:client) do
|
10
22
|
described_class.new.tap do |_client|
|
11
23
|
allow(_client).to receive(:__build_connections)
|
12
24
|
end
|
13
25
|
end
|
14
26
|
|
15
|
-
it 'is aliased as Elasticsearch::Client' do
|
16
|
-
expect(Elasticsearch::Client.new).to be_a(described_class)
|
17
|
-
end
|
18
|
-
|
19
27
|
it 'has a default transport' do
|
20
28
|
expect(client.transport).to be_a(Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS)
|
21
29
|
end
|
@@ -49,7 +57,6 @@ describe Elasticsearch::Transport::Client do
|
|
49
57
|
end
|
50
58
|
|
51
59
|
context 'when a User-Agent header is specified as client option' do
|
52
|
-
|
53
60
|
let(:client) do
|
54
61
|
described_class.new(transport_options: { headers: { 'User-Agent' => 'testing' } })
|
55
62
|
end
|
@@ -59,6 +66,49 @@ describe Elasticsearch::Transport::Client do
|
|
59
66
|
end
|
60
67
|
end
|
61
68
|
|
69
|
+
context 'when an encoded api_key is provided' do
|
70
|
+
let(:client) do
|
71
|
+
described_class.new(api_key: 'an_api_key')
|
72
|
+
end
|
73
|
+
let(:authorization_header) do
|
74
|
+
client.transport.connections.first.connection.headers['Authorization']
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'Adds the ApiKey header to the connection' do
|
78
|
+
expect(authorization_header).to eq('ApiKey an_api_key')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when an un-encoded api_key is provided' do
|
83
|
+
let(:client) do
|
84
|
+
described_class.new(api_key: { id: 'my_id', api_key: 'my_api_key' })
|
85
|
+
end
|
86
|
+
let(:authorization_header) do
|
87
|
+
client.transport.connections.first.connection.headers['Authorization']
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'Adds the ApiKey header to the connection' do
|
91
|
+
expect(authorization_header).to eq("ApiKey #{Base64.strict_encode64('my_id:my_api_key')}")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when basic auth and api_key are provided' do
|
96
|
+
let(:client) do
|
97
|
+
described_class.new(
|
98
|
+
api_key: { id: 'my_id', api_key: 'my_api_key' },
|
99
|
+
host: 'http://elastic:password@localhost:9200'
|
100
|
+
)
|
101
|
+
end
|
102
|
+
let(:authorization_header) do
|
103
|
+
client.transport.connections.first.connection.headers['Authorization']
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'removes basic auth credentials' do
|
107
|
+
expect(authorization_header).not_to match(/^Basic/)
|
108
|
+
expect(authorization_header).to match(/^ApiKey/)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
62
112
|
context 'when a user-agent header is specified as client option in lower-case' do
|
63
113
|
|
64
114
|
let(:client) do
|
@@ -176,47 +226,61 @@ describe Elasticsearch::Transport::Client do
|
|
176
226
|
end
|
177
227
|
|
178
228
|
describe 'adapter' do
|
179
|
-
|
180
229
|
context 'when no adapter is specified' do
|
230
|
+
fork do
|
231
|
+
let(:client) { described_class.new }
|
232
|
+
let(:adapter) { client.transport.connections.all.first.connection.builder.adapter }
|
181
233
|
|
234
|
+
it 'uses Faraday NetHttp' do
|
235
|
+
expect(adapter).to eq Faraday::Adapter::NetHttp
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end unless jruby?
|
239
|
+
|
240
|
+
context 'when the adapter is patron' do
|
182
241
|
let(:adapter) do
|
183
|
-
client.transport.connections.all.first.connection.builder.
|
242
|
+
client.transport.connections.all.first.connection.builder.adapter
|
184
243
|
end
|
185
244
|
|
186
|
-
|
187
|
-
|
245
|
+
let(:client) do
|
246
|
+
described_class.new(adapter: :patron, enable_meta_header: false)
|
188
247
|
end
|
189
|
-
end
|
190
248
|
|
191
|
-
|
249
|
+
it 'uses Faraday with the adapter' do
|
250
|
+
require 'faraday/patron'
|
251
|
+
expect(adapter).to eq Faraday::Adapter::Patron
|
252
|
+
end
|
253
|
+
end unless jruby?
|
192
254
|
|
255
|
+
context 'when the adapter is typhoeus' do
|
193
256
|
let(:adapter) do
|
194
|
-
client.transport.connections.all.first.connection.builder.
|
257
|
+
client.transport.connections.all.first.connection.builder.adapter
|
195
258
|
end
|
196
259
|
|
197
260
|
let(:client) do
|
198
|
-
|
261
|
+
require 'faraday/typhoeus' if is_faraday_v2?
|
262
|
+
|
263
|
+
described_class.new(adapter: :typhoeus, enable_meta_header: false)
|
199
264
|
end
|
200
265
|
|
201
266
|
it 'uses Faraday with the adapter' do
|
202
|
-
expect(adapter).to
|
267
|
+
expect(adapter).to eq Faraday::Adapter::Typhoeus
|
203
268
|
end
|
204
|
-
end
|
269
|
+
end unless jruby?
|
205
270
|
|
206
271
|
context 'when the adapter is specified as a string key' do
|
207
|
-
|
208
272
|
let(:adapter) do
|
209
|
-
client.transport.connections.all.first.connection.builder.
|
273
|
+
client.transport.connections.all.first.connection.builder.adapter
|
210
274
|
end
|
211
275
|
|
212
276
|
let(:client) do
|
213
|
-
described_class.new(
|
277
|
+
described_class.new(adapter: :patron, enable_meta_header: false)
|
214
278
|
end
|
215
279
|
|
216
280
|
it 'uses Faraday with the adapter' do
|
217
|
-
expect(adapter).to
|
281
|
+
expect(adapter).to eq Faraday::Adapter::Patron
|
218
282
|
end
|
219
|
-
end
|
283
|
+
end unless jruby?
|
220
284
|
|
221
285
|
context 'when the adapter can be detected', unless: jruby? do
|
222
286
|
|
@@ -226,11 +290,11 @@ describe Elasticsearch::Transport::Client do
|
|
226
290
|
end
|
227
291
|
|
228
292
|
let(:adapter) do
|
229
|
-
client.transport.connections.all.first.connection.builder.
|
293
|
+
client.transport.connections.all.first.connection.builder.adapter
|
230
294
|
end
|
231
295
|
|
232
296
|
it 'uses the detected adapter' do
|
233
|
-
expect(adapter).to
|
297
|
+
expect(adapter).to eq Faraday::Adapter::Patron
|
234
298
|
end
|
235
299
|
end
|
236
300
|
|
@@ -238,29 +302,37 @@ describe Elasticsearch::Transport::Client do
|
|
238
302
|
|
239
303
|
let(:client) do
|
240
304
|
described_class.new do |faraday|
|
241
|
-
faraday.adapter :
|
305
|
+
faraday.adapter :patron
|
242
306
|
faraday.response :logger
|
243
307
|
end
|
244
308
|
end
|
245
309
|
|
310
|
+
let(:adapter) do
|
311
|
+
client.transport.connections.all.first.connection.builder.adapter
|
312
|
+
end
|
313
|
+
|
246
314
|
let(:handlers) do
|
247
315
|
client.transport.connections.all.first.connection.builder.handlers
|
248
316
|
end
|
249
317
|
|
250
318
|
it 'sets the adapter' do
|
251
|
-
expect(
|
319
|
+
expect(adapter).to eq Faraday::Adapter::Patron
|
252
320
|
end
|
253
321
|
|
254
322
|
it 'sets the logger' do
|
255
323
|
expect(handlers).to include(Faraday::Response::Logger)
|
256
324
|
end
|
257
|
-
end
|
325
|
+
end unless jruby?
|
258
326
|
end
|
259
327
|
|
260
328
|
context 'when cloud credentials are provided' do
|
261
329
|
|
262
330
|
let(:client) do
|
263
|
-
described_class.new(
|
331
|
+
described_class.new(
|
332
|
+
cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
|
333
|
+
user: 'elastic',
|
334
|
+
password: 'changeme'
|
335
|
+
)
|
264
336
|
end
|
265
337
|
|
266
338
|
let(:hosts) do
|
@@ -272,17 +344,19 @@ describe Elasticsearch::Transport::Client do
|
|
272
344
|
expect(hosts[0][:protocol]).to eq('https')
|
273
345
|
expect(hosts[0][:user]).to eq('elastic')
|
274
346
|
expect(hosts[0][:password]).to eq('changeme')
|
275
|
-
expect(hosts[0][:port]).to eq(
|
347
|
+
expect(hosts[0][:port]).to eq(443)
|
276
348
|
end
|
277
349
|
|
278
350
|
it 'creates the correct full url' do
|
279
|
-
expect(
|
351
|
+
expect(
|
352
|
+
client.transport.__full_url(client.transport.hosts[0])
|
353
|
+
).to eq('https://elastic:changeme@abcd.localhost:443')
|
280
354
|
end
|
281
355
|
|
282
356
|
context 'when a port is specified' do
|
283
357
|
|
284
358
|
let(:client) do
|
285
|
-
described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port:
|
359
|
+
described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port: 9250)
|
286
360
|
end
|
287
361
|
|
288
362
|
it 'sets the specified port along with the cloud credentials' do
|
@@ -290,18 +364,22 @@ describe Elasticsearch::Transport::Client do
|
|
290
364
|
expect(hosts[0][:protocol]).to eq('https')
|
291
365
|
expect(hosts[0][:user]).to eq('elastic')
|
292
366
|
expect(hosts[0][:password]).to eq('changeme')
|
293
|
-
expect(hosts[0][:port]).to eq(
|
367
|
+
expect(hosts[0][:port]).to eq(9250)
|
294
368
|
end
|
295
369
|
|
296
370
|
it 'creates the correct full url' do
|
297
|
-
expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:
|
371
|
+
expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:9250')
|
298
372
|
end
|
299
373
|
end
|
300
374
|
|
301
375
|
context 'when the cluster has alternate names' do
|
302
376
|
|
303
377
|
let(:client) do
|
304
|
-
described_class.new(
|
378
|
+
described_class.new(
|
379
|
+
cloud_id: 'myCluster:bG9jYWxob3N0JGFiY2QkZWZnaA==',
|
380
|
+
user: 'elasticfantastic',
|
381
|
+
password: 'tobechanged'
|
382
|
+
)
|
305
383
|
end
|
306
384
|
|
307
385
|
let(:hosts) do
|
@@ -313,124 +391,334 @@ describe Elasticsearch::Transport::Client do
|
|
313
391
|
expect(hosts[0][:protocol]).to eq('https')
|
314
392
|
expect(hosts[0][:user]).to eq('elasticfantastic')
|
315
393
|
expect(hosts[0][:password]).to eq('tobechanged')
|
316
|
-
expect(hosts[0][:port]).to eq(
|
394
|
+
expect(hosts[0][:port]).to eq(443)
|
317
395
|
end
|
318
396
|
|
319
397
|
it 'creates the correct full url' do
|
320
|
-
expect(
|
398
|
+
expect(
|
399
|
+
client.transport.__full_url(client.transport.hosts[0])
|
400
|
+
).to eq('https://elasticfantastic:tobechanged@abcd.localhost:443')
|
321
401
|
end
|
322
|
-
|
323
402
|
end
|
324
|
-
end
|
325
403
|
|
326
|
-
|
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
|
327
412
|
|
328
|
-
|
413
|
+
let(:hosts) do
|
414
|
+
client.transport.hosts
|
415
|
+
end
|
329
416
|
|
330
|
-
|
331
|
-
'
|
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)
|
332
423
|
end
|
333
424
|
|
334
|
-
it '
|
335
|
-
expect(
|
336
|
-
|
337
|
-
|
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')
|
338
429
|
end
|
430
|
+
end
|
339
431
|
|
340
|
-
|
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
|
+
)
|
439
|
+
end
|
341
440
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
example.run
|
346
|
-
Faraday.ignore_env_proxy = original_setting
|
347
|
-
end
|
441
|
+
let(:hosts) do
|
442
|
+
client.transport.hosts
|
443
|
+
end
|
348
444
|
|
349
|
-
|
350
|
-
|
351
|
-
|
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
|
352
453
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
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
|
358
463
|
|
359
|
-
|
360
|
-
|
361
|
-
|
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)
|
362
474
|
end
|
475
|
+
end
|
476
|
+
end
|
363
477
|
|
364
|
-
|
478
|
+
shared_examples_for 'a client that extracts hosts' do
|
365
479
|
|
366
|
-
|
367
|
-
'https://myhost:8080/api'
|
368
|
-
end
|
480
|
+
context 'when the host is a String' do
|
369
481
|
|
370
|
-
|
371
|
-
expect(hosts[0][:host]).to eq('myhost')
|
372
|
-
expect(hosts[0][:scheme]).to eq('https')
|
373
|
-
expect(hosts[0][:path]).to eq('/api')
|
374
|
-
expect(hosts[0][:port]).to be(8080)
|
375
|
-
end
|
376
|
-
end
|
482
|
+
context 'when there is a protocol specified' do
|
377
483
|
|
378
|
-
|
484
|
+
context 'when credentials are specified \'http://USERNAME:PASSWORD@myhost:8080\'' do
|
379
485
|
|
380
|
-
|
381
|
-
|
382
|
-
|
486
|
+
let(:host) do
|
487
|
+
'http://USERNAME:PASSWORD@myhost:8080'
|
488
|
+
end
|
383
489
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
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
|
388
502
|
end
|
389
|
-
end
|
390
503
|
|
391
|
-
|
504
|
+
context 'when there is a trailing slash \'http://myhost/\'' do
|
392
505
|
|
393
|
-
|
394
|
-
|
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
|
395
523
|
end
|
396
524
|
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
525
|
+
context 'when there is a trailing slash with a path \'http://myhost/foo/bar/\'' do
|
526
|
+
|
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
|
403
536
|
end
|
404
|
-
end
|
405
537
|
|
406
|
-
|
538
|
+
context 'when the protocol is http' do
|
407
539
|
|
408
|
-
|
409
|
-
|
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
|
410
607
|
end
|
411
608
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
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
|
416
701
|
end
|
417
702
|
end
|
418
703
|
|
419
|
-
context 'when
|
704
|
+
context 'when no protocol is specified \'myhost\'' do
|
420
705
|
|
421
706
|
let(:host) do
|
422
|
-
'
|
707
|
+
'myhost'
|
423
708
|
end
|
424
709
|
|
425
|
-
it '
|
710
|
+
it 'defaults to http' do
|
426
711
|
expect(hosts[0][:host]).to eq('myhost')
|
427
|
-
expect(hosts[0][:
|
428
|
-
|
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)
|
429
717
|
end
|
430
718
|
end
|
431
719
|
end
|
432
720
|
|
433
|
-
context 'when the
|
721
|
+
context 'when the host is a Hash' do
|
434
722
|
|
435
723
|
let(:host) do
|
436
724
|
{ :host => 'myhost', :scheme => 'https' }
|
@@ -438,7 +726,13 @@ describe Elasticsearch::Transport::Client do
|
|
438
726
|
|
439
727
|
it 'extracts the host' do
|
440
728
|
expect(hosts[0][:host]).to eq('myhost')
|
441
|
-
|
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
|
442
736
|
expect(hosts[0][:port]).to be(9200)
|
443
737
|
end
|
444
738
|
|
@@ -497,7 +791,13 @@ describe Elasticsearch::Transport::Client do
|
|
497
791
|
|
498
792
|
it 'extracts the host' do
|
499
793
|
expect(hosts[0][:host]).to eq('myhost')
|
794
|
+
end
|
795
|
+
|
796
|
+
it 'extracts the protocol' do
|
500
797
|
expect(hosts[0][:scheme]).to eq('https')
|
798
|
+
end
|
799
|
+
|
800
|
+
it 'converts the port to an integer' do
|
501
801
|
expect(hosts[0][:port]).to be(443)
|
502
802
|
end
|
503
803
|
end
|
@@ -510,7 +810,13 @@ describe Elasticsearch::Transport::Client do
|
|
510
810
|
|
511
811
|
it 'extracts the host' do
|
512
812
|
expect(hosts[0][:host]).to eq('myhost')
|
813
|
+
end
|
814
|
+
|
815
|
+
it 'extracts the protocol' do
|
513
816
|
expect(hosts[0][:scheme]).to eq('https')
|
817
|
+
end
|
818
|
+
|
819
|
+
it 'extracts port as an integer' do
|
514
820
|
expect(hosts[0][:port]).to be(443)
|
515
821
|
end
|
516
822
|
end
|
@@ -524,7 +830,13 @@ describe Elasticsearch::Transport::Client do
|
|
524
830
|
|
525
831
|
it 'extracts the host' do
|
526
832
|
expect(hosts[0][:host]).to eq('myhost')
|
833
|
+
end
|
834
|
+
|
835
|
+
it 'extracts the protocol' do
|
527
836
|
expect(hosts[0][:scheme]).to eq('https')
|
837
|
+
end
|
838
|
+
|
839
|
+
it 'converts the port to an integer' do
|
528
840
|
expect(hosts[0][:port]).to be(9200)
|
529
841
|
end
|
530
842
|
|
@@ -536,7 +848,13 @@ describe Elasticsearch::Transport::Client do
|
|
536
848
|
|
537
849
|
it 'extracts the host' do
|
538
850
|
expect(hosts[0][:host]).to eq('myhost')
|
851
|
+
end
|
852
|
+
|
853
|
+
it 'extracts the protocol' do
|
539
854
|
expect(hosts[0][:scheme]).to eq('https')
|
855
|
+
end
|
856
|
+
|
857
|
+
it 'converts the port to an integer' do
|
540
858
|
expect(hosts[0][:port]).to be(443)
|
541
859
|
end
|
542
860
|
end
|
@@ -549,7 +867,13 @@ describe Elasticsearch::Transport::Client do
|
|
549
867
|
|
550
868
|
it 'extracts the host' do
|
551
869
|
expect(hosts[0][:host]).to eq('myhost')
|
870
|
+
end
|
871
|
+
|
872
|
+
it 'extracts the protocol' do
|
552
873
|
expect(hosts[0][:scheme]).to eq('https')
|
874
|
+
end
|
875
|
+
|
876
|
+
it 'extracts port as an integer' do
|
553
877
|
expect(hosts[0][:port]).to be(443)
|
554
878
|
end
|
555
879
|
end
|
@@ -565,7 +889,13 @@ describe Elasticsearch::Transport::Client do
|
|
565
889
|
|
566
890
|
it 'extracts the host' do
|
567
891
|
expect(hosts[0][:host]).to eq('myhost')
|
892
|
+
end
|
893
|
+
|
894
|
+
it 'extracts the protocol' do
|
568
895
|
expect(hosts[0][:protocol]).to eq('http')
|
896
|
+
end
|
897
|
+
|
898
|
+
it 'defaults to port 9200' do
|
569
899
|
expect(hosts[0][:port]).to be(9200)
|
570
900
|
end
|
571
901
|
end
|
@@ -578,20 +908,13 @@ describe Elasticsearch::Transport::Client do
|
|
578
908
|
|
579
909
|
it 'extracts the host' do
|
580
910
|
expect(hosts[0][:host]).to eq('myhost')
|
581
|
-
expect(hosts[0][:protocol]).to eq('http')
|
582
|
-
expect(hosts[0][:port]).to be(9200)
|
583
911
|
end
|
584
|
-
end
|
585
|
-
|
586
|
-
context 'when there is one host with a protocol and no port' do
|
587
912
|
|
588
|
-
|
589
|
-
['http
|
913
|
+
it 'extracts the protocol' do
|
914
|
+
expect(hosts[0][:scheme]).to eq('http')
|
590
915
|
end
|
591
916
|
|
592
|
-
it '
|
593
|
-
expect(hosts[0][:host]).to eq('myhost')
|
594
|
-
expect(hosts[0][:protocol]).to eq('http')
|
917
|
+
it 'defaults to port 9200' do
|
595
918
|
expect(hosts[0][:port]).to be(9200)
|
596
919
|
end
|
597
920
|
end
|
@@ -616,7 +939,7 @@ describe Elasticsearch::Transport::Client do
|
|
616
939
|
end
|
617
940
|
end
|
618
941
|
|
619
|
-
context 'when there is one host with a
|
942
|
+
context 'when there is one host with a protocol and no port' do
|
620
943
|
|
621
944
|
let(:host) do
|
622
945
|
['https://myhost']
|
@@ -624,12 +947,18 @@ describe Elasticsearch::Transport::Client do
|
|
624
947
|
|
625
948
|
it 'extracts the host' do
|
626
949
|
expect(hosts[0][:host]).to eq('myhost')
|
627
|
-
|
628
|
-
|
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)
|
629
958
|
end
|
630
959
|
end
|
631
960
|
|
632
|
-
context 'when there is one host with a
|
961
|
+
context 'when there is one host with a protocol, path, and no port' do
|
633
962
|
|
634
963
|
let(:host) do
|
635
964
|
['http://myhost/foo/bar']
|
@@ -637,9 +966,18 @@ describe Elasticsearch::Transport::Client do
|
|
637
966
|
|
638
967
|
it 'extracts the host' do
|
639
968
|
expect(hosts[0][:host]).to eq('myhost')
|
640
|
-
|
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
|
641
976
|
expect(hosts[0][:port]).to be(9200)
|
642
|
-
|
977
|
+
end
|
978
|
+
|
979
|
+
it 'extracts the path' do
|
980
|
+
expect(hosts[0][:path]).to eq('/foo/bar')
|
643
981
|
end
|
644
982
|
end
|
645
983
|
|
@@ -649,7 +987,7 @@ describe Elasticsearch::Transport::Client do
|
|
649
987
|
['host1', 'host2']
|
650
988
|
end
|
651
989
|
|
652
|
-
it 'extracts the
|
990
|
+
it 'extracts the hosts' do
|
653
991
|
expect(hosts[0][:host]).to eq('host1')
|
654
992
|
expect(hosts[0][:protocol]).to eq('http')
|
655
993
|
expect(hosts[0][:port]).to be(9200)
|
@@ -665,7 +1003,7 @@ describe Elasticsearch::Transport::Client do
|
|
665
1003
|
['host1:1000', 'host2:2000']
|
666
1004
|
end
|
667
1005
|
|
668
|
-
it 'extracts the
|
1006
|
+
it 'extracts the hosts' do
|
669
1007
|
expect(hosts[0][:host]).to eq('host1')
|
670
1008
|
expect(hosts[0][:protocol]).to eq('http')
|
671
1009
|
expect(hosts[0][:port]).to be(1000)
|
@@ -1055,10 +1393,130 @@ describe Elasticsearch::Transport::Client do
|
|
1055
1393
|
expect(request).to be(true)
|
1056
1394
|
end
|
1057
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.perform_request('GET', '_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.perform_request('GET', '_search', {}, nil, opaque_id: 'opaque_id') }.not_to raise_error
|
1425
|
+
expect(client).to have_received(:perform_request)
|
1426
|
+
.with('GET', '_search', {}, nil, { opaque_id: 'opaque_id' })
|
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
|
+
ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
|
1441
|
+
end
|
1442
|
+
|
1443
|
+
it 'does not use API compatibility headers' do
|
1444
|
+
val = ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
|
1445
|
+
client = described_class.new(host: hosts)
|
1446
|
+
expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
|
1447
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = val
|
1448
|
+
end
|
1449
|
+
|
1450
|
+
it 'does not use API compatibility headers when it is set to unsupported values' do
|
1451
|
+
val = ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
|
1452
|
+
|
1453
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = 'test'
|
1454
|
+
client = described_class.new(host: hosts)
|
1455
|
+
expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
|
1456
|
+
|
1457
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = 'false'
|
1458
|
+
client = described_class.new(host: hosts)
|
1459
|
+
expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
|
1460
|
+
|
1461
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = '3'
|
1462
|
+
client = described_class.new(host: hosts)
|
1463
|
+
expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
|
1464
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = val
|
1465
|
+
end
|
1466
|
+
end
|
1467
|
+
|
1468
|
+
context 'when Elasticsearch response includes a warning header' do
|
1469
|
+
let(:logger) { double('logger', warn: '', warn?: '', info?: '', info: '', debug?: '', debug: '') }
|
1470
|
+
let(:client) do
|
1471
|
+
Elasticsearch::Transport::Client.new(hosts: hosts, logger: logger)
|
1472
|
+
end
|
1473
|
+
|
1474
|
+
let(:warning) { 'Elasticsearch warning: "deprecation warning"' }
|
1475
|
+
|
1476
|
+
it 'prints a warning' do
|
1477
|
+
expect_any_instance_of(Faraday::Connection).to receive(:run_request) do
|
1478
|
+
Elasticsearch::Transport::Transport::Response.new(200, {}, { 'warning' => warning })
|
1479
|
+
end
|
1480
|
+
client.perform_request('GET', '/')
|
1481
|
+
expect(logger).to have_received(:warn).with(warning)
|
1482
|
+
end
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
context 'when a header is set on an endpoint request' do
|
1486
|
+
let(:client) { described_class.new(host: hosts) }
|
1487
|
+
let(:headers) { { 'user-agent' => 'my ruby app' } }
|
1488
|
+
|
1489
|
+
it 'performs the request with the header' do
|
1490
|
+
allow(client).to receive(:perform_request) { OpenStruct.new(body: '') }
|
1491
|
+
expect { client.perform_request('GET', '_search', {}, nil, headers) }.not_to raise_error
|
1492
|
+
expect(client).to have_received(:perform_request)
|
1493
|
+
.with('GET', '_search', {}, nil, headers)
|
1494
|
+
end
|
1495
|
+
end
|
1496
|
+
|
1497
|
+
context 'when a header is set on an endpoint request and on initialization' do
|
1498
|
+
let!(:client) do
|
1499
|
+
described_class.new(
|
1500
|
+
host: hosts,
|
1501
|
+
transport_options: { headers: instance_headers }
|
1502
|
+
)
|
1503
|
+
end
|
1504
|
+
let(:instance_headers) { { set_in_instantiation: 'header value' } }
|
1505
|
+
let(:param_headers) { {'user-agent' => 'My Ruby Tests', 'set-on-method-call' => 'header value'} }
|
1506
|
+
|
1507
|
+
it 'performs the request with the header' do
|
1508
|
+
expected_headers = client.transport.connections.connections.first.connection.headers.merge(param_headers)
|
1509
|
+
|
1510
|
+
expect_any_instance_of(Faraday::Connection)
|
1511
|
+
.to receive(:run_request)
|
1512
|
+
.with(:get, "http://#{hosts[0]}/_search", nil, expected_headers) { OpenStruct.new(body: '')}
|
1513
|
+
|
1514
|
+
client.perform_request('GET', '_search', {}, nil, param_headers)
|
1515
|
+
end
|
1516
|
+
end
|
1058
1517
|
end
|
1059
1518
|
|
1060
1519
|
context 'when the client connects to Elasticsearch' do
|
1061
|
-
|
1062
1520
|
let(:logger) do
|
1063
1521
|
Logger.new(STDERR).tap do |logger|
|
1064
1522
|
logger.formatter = proc do |severity, datetime, progname, msg|
|
@@ -1090,7 +1548,6 @@ describe Elasticsearch::Transport::Client do
|
|
1090
1548
|
end
|
1091
1549
|
|
1092
1550
|
context 'when a request is made' do
|
1093
|
-
|
1094
1551
|
let!(:response) do
|
1095
1552
|
client.perform_request('GET', '_cluster/health')
|
1096
1553
|
end
|
@@ -1101,9 +1558,7 @@ describe Elasticsearch::Transport::Client do
|
|
1101
1558
|
end
|
1102
1559
|
|
1103
1560
|
describe '#initialize' do
|
1104
|
-
|
1105
1561
|
context 'when options are specified' do
|
1106
|
-
|
1107
1562
|
let(:transport_options) do
|
1108
1563
|
{ headers: { accept: 'application/yaml', content_type: 'application/yaml' } }
|
1109
1564
|
end
|
@@ -1119,9 +1574,8 @@ describe Elasticsearch::Transport::Client do
|
|
1119
1574
|
end
|
1120
1575
|
|
1121
1576
|
context 'when a block is provided' do
|
1122
|
-
|
1123
1577
|
let(:client) do
|
1124
|
-
|
1578
|
+
described_class.new(host: ELASTICSEARCH_HOSTS.first, logger: logger) do |client|
|
1125
1579
|
client.headers['Accept'] = 'application/yaml'
|
1126
1580
|
end
|
1127
1581
|
end
|
@@ -1136,15 +1590,16 @@ describe Elasticsearch::Transport::Client do
|
|
1136
1590
|
end
|
1137
1591
|
|
1138
1592
|
context 'when the Faraday adapter is set in the block' do
|
1593
|
+
require 'faraday/net_http_persistent' if is_faraday_v2?
|
1139
1594
|
|
1140
1595
|
let(:client) do
|
1141
|
-
|
1596
|
+
described_class.new(host: ELASTICSEARCH_HOSTS.first, logger: logger) do |client|
|
1142
1597
|
client.adapter(:net_http_persistent)
|
1143
1598
|
end
|
1144
1599
|
end
|
1145
1600
|
|
1146
|
-
let(:
|
1147
|
-
client.transport.connections.first.connection.builder.
|
1601
|
+
let(:handler_name) do
|
1602
|
+
client.transport.connections.first.connection.builder.adapter.name
|
1148
1603
|
end
|
1149
1604
|
|
1150
1605
|
let(:response) do
|
@@ -1152,7 +1607,7 @@ describe Elasticsearch::Transport::Client do
|
|
1152
1607
|
end
|
1153
1608
|
|
1154
1609
|
it 'sets the adapter' do
|
1155
|
-
expect(
|
1610
|
+
expect(handler_name).to eq('Faraday::Adapter::NetHttpPersistent')
|
1156
1611
|
end
|
1157
1612
|
|
1158
1613
|
it 'uses the adapter to connect' do
|
@@ -1202,7 +1657,30 @@ describe Elasticsearch::Transport::Client do
|
|
1202
1657
|
expect(client.perform_request('GET', '_nodes/_local'))
|
1203
1658
|
expect {
|
1204
1659
|
client.perform_request('GET', '_nodes/_local')
|
1205
|
-
}.to raise_exception(Faraday::
|
1660
|
+
}.to raise_exception(Faraday::ConnectionFailed)
|
1661
|
+
end
|
1662
|
+
end
|
1663
|
+
|
1664
|
+
context 'when retry_on_failure is true and delay_on_retry is specified' do
|
1665
|
+
context 'when a node is unreachable' do
|
1666
|
+
let(:hosts) do
|
1667
|
+
[ELASTICSEARCH_HOSTS.first, "foobar1", "foobar2"]
|
1668
|
+
end
|
1669
|
+
|
1670
|
+
let(:options) do
|
1671
|
+
{ retry_on_failure: true, delay_on_retry: 3000 }
|
1672
|
+
end
|
1673
|
+
|
1674
|
+
let(:responses) do
|
1675
|
+
5.times.collect do
|
1676
|
+
client.perform_request('GET', '_nodes/_local')
|
1677
|
+
end
|
1678
|
+
end
|
1679
|
+
|
1680
|
+
it 'retries on failure' do
|
1681
|
+
allow_any_instance_of(Object).to receive(:sleep).with(3000 / 1000)
|
1682
|
+
expect(responses.all? { true }).to be(true)
|
1683
|
+
end
|
1206
1684
|
end
|
1207
1685
|
end
|
1208
1686
|
|
@@ -1265,7 +1743,7 @@ describe Elasticsearch::Transport::Client do
|
|
1265
1743
|
end
|
1266
1744
|
|
1267
1745
|
it 'sets the Accept-Encoding header' do
|
1268
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1746
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1269
1747
|
end
|
1270
1748
|
|
1271
1749
|
it 'preserves the other headers' do
|
@@ -1274,9 +1752,10 @@ describe Elasticsearch::Transport::Client do
|
|
1274
1752
|
end
|
1275
1753
|
|
1276
1754
|
context 'when using the HTTPClient adapter' do
|
1755
|
+
require 'faraday/httpclient'
|
1277
1756
|
|
1278
1757
|
let(:client) do
|
1279
|
-
described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :httpclient)
|
1758
|
+
described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :httpclient, enable_meta_header: false)
|
1280
1759
|
end
|
1281
1760
|
|
1282
1761
|
it 'compresses the request and decompresses the response' do
|
@@ -1284,7 +1763,7 @@ describe Elasticsearch::Transport::Client do
|
|
1284
1763
|
end
|
1285
1764
|
|
1286
1765
|
it 'sets the Accept-Encoding header' do
|
1287
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1766
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1288
1767
|
end
|
1289
1768
|
|
1290
1769
|
it 'preserves the other headers' do
|
@@ -1303,7 +1782,7 @@ describe Elasticsearch::Transport::Client do
|
|
1303
1782
|
end
|
1304
1783
|
|
1305
1784
|
it 'sets the Accept-Encoding header' do
|
1306
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1785
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1307
1786
|
end
|
1308
1787
|
|
1309
1788
|
it 'preserves the other headers' do
|
@@ -1322,7 +1801,7 @@ describe Elasticsearch::Transport::Client do
|
|
1322
1801
|
end
|
1323
1802
|
|
1324
1803
|
it 'sets the Accept-Encoding header' do
|
1325
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1804
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1326
1805
|
end
|
1327
1806
|
|
1328
1807
|
it 'preserves the other headers' do
|
@@ -1341,22 +1820,23 @@ describe Elasticsearch::Transport::Client do
|
|
1341
1820
|
end
|
1342
1821
|
|
1343
1822
|
it 'sets the Accept-Encoding header' do
|
1344
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1823
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1345
1824
|
end
|
1346
1825
|
|
1347
1826
|
it 'preserves the other headers' do
|
1348
1827
|
expect(client.transport.connections[0].connection.headers['User-Agent'])
|
1349
1828
|
end
|
1350
|
-
end
|
1829
|
+
end unless jruby?
|
1351
1830
|
end
|
1352
1831
|
end
|
1353
1832
|
|
1354
1833
|
context 'when using Curb as the transport', unless: jruby? do
|
1355
|
-
|
1356
1834
|
let(:client) do
|
1357
|
-
described_class.new(
|
1358
|
-
|
1359
|
-
|
1835
|
+
described_class.new(
|
1836
|
+
hosts: ELASTICSEARCH_HOSTS,
|
1837
|
+
compression: true,
|
1838
|
+
transport_class: Elasticsearch::Transport::Transport::HTTP::Curb
|
1839
|
+
)
|
1360
1840
|
end
|
1361
1841
|
|
1362
1842
|
it 'compresses the request and decompresses the response' do
|
@@ -1364,7 +1844,7 @@ describe Elasticsearch::Transport::Client do
|
|
1364
1844
|
end
|
1365
1845
|
|
1366
1846
|
it 'sets the Accept-Encoding header' do
|
1367
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1847
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1368
1848
|
end
|
1369
1849
|
|
1370
1850
|
it 'preserves the other headers' do
|
@@ -1373,7 +1853,6 @@ describe Elasticsearch::Transport::Client do
|
|
1373
1853
|
end
|
1374
1854
|
|
1375
1855
|
context 'when using Manticore as the transport', if: jruby? do
|
1376
|
-
|
1377
1856
|
let(:client) do
|
1378
1857
|
described_class.new(hosts: ELASTICSEARCH_HOSTS,
|
1379
1858
|
compression: true,
|
@@ -1387,9 +1866,7 @@ describe Elasticsearch::Transport::Client do
|
|
1387
1866
|
end
|
1388
1867
|
|
1389
1868
|
describe '#perform_request' do
|
1390
|
-
|
1391
1869
|
context 'when a request is made' do
|
1392
|
-
|
1393
1870
|
before do
|
1394
1871
|
client.perform_request('DELETE', '_all')
|
1395
1872
|
client.perform_request('DELETE', 'myindex') rescue
|
@@ -1412,7 +1889,6 @@ describe Elasticsearch::Transport::Client do
|
|
1412
1889
|
end
|
1413
1890
|
|
1414
1891
|
context 'when an invalid url is specified' do
|
1415
|
-
|
1416
1892
|
it 'raises an exception' do
|
1417
1893
|
expect {
|
1418
1894
|
client.perform_request('GET', 'myindex/mydoc/1?routing=FOOBARBAZ')
|
@@ -1421,7 +1897,6 @@ describe Elasticsearch::Transport::Client do
|
|
1421
1897
|
end
|
1422
1898
|
|
1423
1899
|
context 'when the \'ignore\' parameter is specified' do
|
1424
|
-
|
1425
1900
|
let(:response) do
|
1426
1901
|
client.perform_request('PUT', '_foobar', ignore: 400)
|
1427
1902
|
end
|
@@ -1437,7 +1912,6 @@ describe Elasticsearch::Transport::Client do
|
|
1437
1912
|
end
|
1438
1913
|
|
1439
1914
|
context 'when request headers are specified' do
|
1440
|
-
|
1441
1915
|
let(:response) do
|
1442
1916
|
client.perform_request('GET', '/', {}, nil, { 'Content-Type' => 'application/yaml' })
|
1443
1917
|
end
|
@@ -1448,9 +1922,7 @@ describe Elasticsearch::Transport::Client do
|
|
1448
1922
|
end
|
1449
1923
|
|
1450
1924
|
describe 'selector' do
|
1451
|
-
|
1452
1925
|
context 'when the round-robin selector is used' do
|
1453
|
-
|
1454
1926
|
let(:nodes) do
|
1455
1927
|
3.times.collect do
|
1456
1928
|
client.perform_request('GET', '_nodes/_local').body['nodes'].to_a[0][1]['name']
|
@@ -1458,7 +1930,7 @@ describe Elasticsearch::Transport::Client do
|
|
1458
1930
|
end
|
1459
1931
|
|
1460
1932
|
let(:node_names) do
|
1461
|
-
client.
|
1933
|
+
client.perform_request('GET', '_nodes/stats').body('nodes').collect do |name, stats|
|
1462
1934
|
stats['name']
|
1463
1935
|
end
|
1464
1936
|
end
|
@@ -1477,7 +1949,6 @@ describe Elasticsearch::Transport::Client do
|
|
1477
1949
|
end
|
1478
1950
|
|
1479
1951
|
context 'when patron is used as an adapter', unless: jruby? do
|
1480
|
-
|
1481
1952
|
before do
|
1482
1953
|
require 'patron'
|
1483
1954
|
end
|
@@ -1486,12 +1957,39 @@ describe Elasticsearch::Transport::Client do
|
|
1486
1957
|
{ adapter: :patron }
|
1487
1958
|
end
|
1488
1959
|
|
1489
|
-
let(:
|
1490
|
-
client.transport.connections.first.connection.builder.
|
1960
|
+
let(:adapter) do
|
1961
|
+
client.transport.connections.first.connection.builder.adapter
|
1962
|
+
end
|
1963
|
+
|
1964
|
+
it 'uses the patron connection handler' do
|
1965
|
+
expect(adapter).to eq('Faraday::Adapter::Patron')
|
1966
|
+
end
|
1967
|
+
|
1968
|
+
it 'keeps connections open' do
|
1969
|
+
response = client.perform_request('GET', '_nodes/stats/http')
|
1970
|
+
connections_before = response.body['nodes'].values.find { |n| n['name'] == node_names.first }['http']['total_opened']
|
1971
|
+
client.transport.reload_connections!
|
1972
|
+
response = client.perform_request('GET', '_nodes/stats/http')
|
1973
|
+
connections_after = response.body['nodes'].values.find { |n| n['name'] == node_names.first }['http']['total_opened']
|
1974
|
+
expect(connections_after).to be >= (connections_before)
|
1975
|
+
end
|
1976
|
+
end
|
1977
|
+
|
1978
|
+
context 'when typhoeus is used as an adapter', unless: jruby? do
|
1979
|
+
before do
|
1980
|
+
require 'typhoeus'
|
1981
|
+
end
|
1982
|
+
|
1983
|
+
let(:options) do
|
1984
|
+
{ adapter: :typhoeus }
|
1985
|
+
end
|
1986
|
+
|
1987
|
+
let(:adapter) do
|
1988
|
+
client.transport.connections.first.connection.builder.adapter
|
1491
1989
|
end
|
1492
1990
|
|
1493
1991
|
it 'uses the patron connection handler' do
|
1494
|
-
expect(
|
1992
|
+
expect(adapter).to eq('Faraday::Adapter::Typhoeus')
|
1495
1993
|
end
|
1496
1994
|
|
1497
1995
|
it 'keeps connections open' do
|
@@ -1505,4 +2003,76 @@ describe Elasticsearch::Transport::Client do
|
|
1505
2003
|
end
|
1506
2004
|
end
|
1507
2005
|
end
|
2006
|
+
|
2007
|
+
context 'CA Fingerprinting' do
|
2008
|
+
context 'when setting a ca_fingerprint' do
|
2009
|
+
after do
|
2010
|
+
File.delete('./certificate.crt')
|
2011
|
+
File.delete('./certificate.key')
|
2012
|
+
end
|
2013
|
+
|
2014
|
+
let(:certificate) do
|
2015
|
+
system(
|
2016
|
+
'openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -subj "/C=BE/O=Test/CN=Test"' \
|
2017
|
+
' -keyout certificate.key -out certificate.crt',
|
2018
|
+
err: File::NULL
|
2019
|
+
)
|
2020
|
+
OpenSSL::X509::Certificate.new File.read('./certificate.crt')
|
2021
|
+
end
|
2022
|
+
|
2023
|
+
let(:client) do
|
2024
|
+
Elasticsearch::Transport::Client.new(
|
2025
|
+
host: 'https://elastic:changeme@localhost:9200',
|
2026
|
+
ca_fingerprint: OpenSSL::Digest::SHA256.hexdigest(certificate.to_der)
|
2027
|
+
)
|
2028
|
+
end
|
2029
|
+
|
2030
|
+
it 'validates CA fingerprints on perform request' do
|
2031
|
+
expect(client.transport.connections.connections.map(&:verified).uniq).to eq [false]
|
2032
|
+
allow(client.transport).to receive(:perform_request) { 'Hello' }
|
2033
|
+
|
2034
|
+
server = double('server').as_null_object
|
2035
|
+
allow(TCPSocket).to receive(:new) { server }
|
2036
|
+
socket = double('socket')
|
2037
|
+
allow(OpenSSL::SSL::SSLSocket).to receive(:new) { socket }
|
2038
|
+
allow(socket).to receive(:connect) { nil }
|
2039
|
+
allow(socket).to receive(:peer_cert_chain) { [certificate] }
|
2040
|
+
|
2041
|
+
response = client.perform_request('GET', '/')
|
2042
|
+
expect(client.transport.connections.connections.map(&:verified).uniq).to eq [true]
|
2043
|
+
expect(response).to eq 'Hello'
|
2044
|
+
end
|
2045
|
+
end
|
2046
|
+
|
2047
|
+
context 'when using an http host' do
|
2048
|
+
let(:client) do
|
2049
|
+
Elasticsearch::Transport::Client.new(
|
2050
|
+
host: 'http://elastic:changeme@localhost:9200',
|
2051
|
+
ca_fingerprint: 'test'
|
2052
|
+
)
|
2053
|
+
end
|
2054
|
+
|
2055
|
+
it 'raises an error' do
|
2056
|
+
expect do
|
2057
|
+
client.perform_request('GET', '/')
|
2058
|
+
end.to raise_exception(Elasticsearch::Transport::Transport::Error)
|
2059
|
+
end
|
2060
|
+
end
|
2061
|
+
|
2062
|
+
context 'when not setting a ca_fingerprint' do
|
2063
|
+
let(:client) do
|
2064
|
+
Elasticsearch::Transport::Client.new(
|
2065
|
+
host: 'http://elastic:changeme@localhost:9200'
|
2066
|
+
)
|
2067
|
+
end
|
2068
|
+
|
2069
|
+
it 'has unvalidated connections' do
|
2070
|
+
allow(client).to receive(:validate_ca_fingerprints) { nil }
|
2071
|
+
allow(client.transport).to receive(:perform_request) { nil }
|
2072
|
+
|
2073
|
+
client.perform_request('GET', '/')
|
2074
|
+
expect(client).to_not have_received(:validate_ca_fingerprints)
|
2075
|
+
end
|
2076
|
+
end
|
2077
|
+
end
|
1508
2078
|
end
|