elasticsearch-transport 7.5.0 → 7.17.7
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 +26 -13
- data/README.md +159 -64
- data/Rakefile +25 -13
- data/elasticsearch-transport.gemspec +57 -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 +51 -31
- data/lib/elasticsearch/transport/transport/loggable.rb +16 -3
- data/lib/elasticsearch/transport/transport/response.rb +16 -4
- data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +16 -3
- data/lib/elasticsearch/transport/transport/sniffer.rb +35 -15
- data/lib/elasticsearch/transport/version.rb +17 -4
- data/lib/elasticsearch/transport.rb +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 +104 -43
- data/spec/elasticsearch/transport/client_spec.rb +727 -163
- 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 +143 -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 +28 -6
- data/test/integration/jruby_test.rb +43 -0
- data/test/integration/transport_test.rb +46 -29
- data/test/profile/client_benchmark_test.rb +16 -3
- data/test/test_helper.rb +22 -25
- 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 +80 -71
@@ -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,45 +226,56 @@ 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 unless jruby?
|
238
|
+
end
|
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
|
+
expect(adapter).to eq Faraday::Adapter::Patron
|
251
|
+
end
|
252
|
+
end
|
192
253
|
|
254
|
+
context 'when the adapter is typhoeus' do
|
193
255
|
let(:adapter) do
|
194
|
-
client.transport.connections.all.first.connection.builder.
|
256
|
+
client.transport.connections.all.first.connection.builder.adapter
|
195
257
|
end
|
196
258
|
|
197
259
|
let(:client) do
|
198
|
-
described_class.new(adapter: :typhoeus)
|
260
|
+
described_class.new(adapter: :typhoeus, enable_meta_header: false)
|
199
261
|
end
|
200
262
|
|
201
263
|
it 'uses Faraday with the adapter' do
|
202
|
-
expect(adapter).to
|
264
|
+
expect(adapter).to eq Faraday::Adapter::Typhoeus
|
203
265
|
end
|
204
|
-
end
|
266
|
+
end unless jruby?
|
205
267
|
|
206
268
|
context 'when the adapter is specified as a string key' do
|
207
|
-
|
208
269
|
let(:adapter) do
|
209
|
-
client.transport.connections.all.first.connection.builder.
|
270
|
+
client.transport.connections.all.first.connection.builder.adapter
|
210
271
|
end
|
211
272
|
|
212
273
|
let(:client) do
|
213
|
-
described_class.new(
|
274
|
+
described_class.new(adapter: :patron, enable_meta_header: false)
|
214
275
|
end
|
215
276
|
|
216
277
|
it 'uses Faraday with the adapter' do
|
217
|
-
expect(adapter).to
|
278
|
+
expect(adapter).to eq Faraday::Adapter::Patron
|
218
279
|
end
|
219
280
|
end
|
220
281
|
|
@@ -226,11 +287,11 @@ describe Elasticsearch::Transport::Client do
|
|
226
287
|
end
|
227
288
|
|
228
289
|
let(:adapter) do
|
229
|
-
client.transport.connections.all.first.connection.builder.
|
290
|
+
client.transport.connections.all.first.connection.builder.adapter
|
230
291
|
end
|
231
292
|
|
232
293
|
it 'uses the detected adapter' do
|
233
|
-
expect(adapter).to
|
294
|
+
expect(adapter).to eq Faraday::Adapter::Patron
|
234
295
|
end
|
235
296
|
end
|
236
297
|
|
@@ -238,17 +299,21 @@ describe Elasticsearch::Transport::Client do
|
|
238
299
|
|
239
300
|
let(:client) do
|
240
301
|
described_class.new do |faraday|
|
241
|
-
faraday.adapter :
|
302
|
+
faraday.adapter :patron
|
242
303
|
faraday.response :logger
|
243
304
|
end
|
244
305
|
end
|
245
306
|
|
307
|
+
let(:adapter) do
|
308
|
+
client.transport.connections.all.first.connection.builder.adapter
|
309
|
+
end
|
310
|
+
|
246
311
|
let(:handlers) do
|
247
312
|
client.transport.connections.all.first.connection.builder.handlers
|
248
313
|
end
|
249
314
|
|
250
315
|
it 'sets the adapter' do
|
251
|
-
expect(
|
316
|
+
expect(adapter).to eq Faraday::Adapter::Patron
|
252
317
|
end
|
253
318
|
|
254
319
|
it 'sets the logger' do
|
@@ -260,7 +325,11 @@ describe Elasticsearch::Transport::Client do
|
|
260
325
|
context 'when cloud credentials are provided' do
|
261
326
|
|
262
327
|
let(:client) do
|
263
|
-
described_class.new(
|
328
|
+
described_class.new(
|
329
|
+
cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
|
330
|
+
user: 'elastic',
|
331
|
+
password: 'changeme'
|
332
|
+
)
|
264
333
|
end
|
265
334
|
|
266
335
|
let(:hosts) do
|
@@ -272,17 +341,19 @@ describe Elasticsearch::Transport::Client do
|
|
272
341
|
expect(hosts[0][:protocol]).to eq('https')
|
273
342
|
expect(hosts[0][:user]).to eq('elastic')
|
274
343
|
expect(hosts[0][:password]).to eq('changeme')
|
275
|
-
expect(hosts[0][:port]).to eq(
|
344
|
+
expect(hosts[0][:port]).to eq(443)
|
276
345
|
end
|
277
346
|
|
278
347
|
it 'creates the correct full url' do
|
279
|
-
expect(
|
348
|
+
expect(
|
349
|
+
client.transport.__full_url(client.transport.hosts[0])
|
350
|
+
).to eq('https://elastic:changeme@abcd.localhost:443')
|
280
351
|
end
|
281
352
|
|
282
353
|
context 'when a port is specified' do
|
283
354
|
|
284
355
|
let(:client) do
|
285
|
-
described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port:
|
356
|
+
described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port: 9250)
|
286
357
|
end
|
287
358
|
|
288
359
|
it 'sets the specified port along with the cloud credentials' do
|
@@ -290,18 +361,22 @@ describe Elasticsearch::Transport::Client do
|
|
290
361
|
expect(hosts[0][:protocol]).to eq('https')
|
291
362
|
expect(hosts[0][:user]).to eq('elastic')
|
292
363
|
expect(hosts[0][:password]).to eq('changeme')
|
293
|
-
expect(hosts[0][:port]).to eq(
|
364
|
+
expect(hosts[0][:port]).to eq(9250)
|
294
365
|
end
|
295
366
|
|
296
367
|
it 'creates the correct full url' do
|
297
|
-
expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:
|
368
|
+
expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:9250')
|
298
369
|
end
|
299
370
|
end
|
300
371
|
|
301
372
|
context 'when the cluster has alternate names' do
|
302
373
|
|
303
374
|
let(:client) do
|
304
|
-
described_class.new(
|
375
|
+
described_class.new(
|
376
|
+
cloud_id: 'myCluster:bG9jYWxob3N0JGFiY2QkZWZnaA==',
|
377
|
+
user: 'elasticfantastic',
|
378
|
+
password: 'tobechanged'
|
379
|
+
)
|
305
380
|
end
|
306
381
|
|
307
382
|
let(:hosts) do
|
@@ -313,124 +388,334 @@ describe Elasticsearch::Transport::Client do
|
|
313
388
|
expect(hosts[0][:protocol]).to eq('https')
|
314
389
|
expect(hosts[0][:user]).to eq('elasticfantastic')
|
315
390
|
expect(hosts[0][:password]).to eq('tobechanged')
|
316
|
-
expect(hosts[0][:port]).to eq(
|
391
|
+
expect(hosts[0][:port]).to eq(443)
|
317
392
|
end
|
318
393
|
|
319
394
|
it 'creates the correct full url' do
|
320
|
-
expect(
|
395
|
+
expect(
|
396
|
+
client.transport.__full_url(client.transport.hosts[0])
|
397
|
+
).to eq('https://elasticfantastic:tobechanged@abcd.localhost:443')
|
321
398
|
end
|
322
|
-
|
323
399
|
end
|
324
|
-
end
|
325
400
|
|
326
|
-
|
401
|
+
context 'when decoded cloud id has a trailing dollar sign' do
|
402
|
+
let(:client) do
|
403
|
+
described_class.new(
|
404
|
+
cloud_id: 'a_cluster:bG9jYWxob3N0JGFiY2Qk',
|
405
|
+
user: 'elasticfantastic',
|
406
|
+
password: 'changeme'
|
407
|
+
)
|
408
|
+
end
|
327
409
|
|
328
|
-
|
410
|
+
let(:hosts) do
|
411
|
+
client.transport.hosts
|
412
|
+
end
|
329
413
|
|
330
|
-
|
331
|
-
'
|
414
|
+
it 'extracts the cloud credentials' do
|
415
|
+
expect(hosts[0][:host]).to eq('abcd.localhost')
|
416
|
+
expect(hosts[0][:protocol]).to eq('https')
|
417
|
+
expect(hosts[0][:user]).to eq('elasticfantastic')
|
418
|
+
expect(hosts[0][:password]).to eq('changeme')
|
419
|
+
expect(hosts[0][:port]).to eq(443)
|
332
420
|
end
|
333
421
|
|
334
|
-
it '
|
335
|
-
expect(
|
336
|
-
|
337
|
-
|
422
|
+
it 'creates the correct full url' do
|
423
|
+
expect(
|
424
|
+
client.transport.__full_url(client.transport.hosts[0])
|
425
|
+
).to eq('https://elasticfantastic:changeme@abcd.localhost:443')
|
338
426
|
end
|
427
|
+
end
|
339
428
|
|
340
|
-
|
429
|
+
context 'when the cloud host provides a port' do
|
430
|
+
let(:client) do
|
431
|
+
described_class.new(
|
432
|
+
cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk',
|
433
|
+
user: 'elastic',
|
434
|
+
password: 'changeme'
|
435
|
+
)
|
436
|
+
end
|
341
437
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
example.run
|
346
|
-
Faraday.ignore_env_proxy = original_setting
|
347
|
-
end
|
438
|
+
let(:hosts) do
|
439
|
+
client.transport.hosts
|
440
|
+
end
|
348
441
|
|
349
|
-
|
350
|
-
|
351
|
-
|
442
|
+
it 'creates the correct full url' do
|
443
|
+
expect(hosts[0][:host]).to eq('elastic_id.elastic_server')
|
444
|
+
expect(hosts[0][:protocol]).to eq('https')
|
445
|
+
expect(hosts[0][:user]).to eq('elastic')
|
446
|
+
expect(hosts[0][:password]).to eq('changeme')
|
447
|
+
expect(hosts[0][:port]).to eq(9243)
|
448
|
+
end
|
449
|
+
end
|
352
450
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
451
|
+
context 'when the cloud host provides a port and the port is also specified' do
|
452
|
+
let(:client) do
|
453
|
+
described_class.new(
|
454
|
+
cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk',
|
455
|
+
user: 'elastic',
|
456
|
+
password: 'changeme',
|
457
|
+
port: 9200
|
458
|
+
)
|
459
|
+
end
|
358
460
|
|
359
|
-
|
360
|
-
|
361
|
-
end
|
461
|
+
let(:hosts) do
|
462
|
+
client.transport.hosts
|
362
463
|
end
|
363
464
|
|
364
|
-
|
465
|
+
it 'creates the correct full url' do
|
466
|
+
expect(hosts[0][:host]).to eq('elastic_id.elastic_server')
|
467
|
+
expect(hosts[0][:protocol]).to eq('https')
|
468
|
+
expect(hosts[0][:user]).to eq('elastic')
|
469
|
+
expect(hosts[0][:password]).to eq('changeme')
|
470
|
+
expect(hosts[0][:port]).to eq(9243)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
365
474
|
|
366
|
-
|
367
|
-
'https://myhost:8080/api'
|
368
|
-
end
|
475
|
+
shared_examples_for 'a client that extracts hosts' do
|
369
476
|
|
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
|
477
|
+
context 'when the host is a String' do
|
377
478
|
|
378
|
-
context 'when a
|
479
|
+
context 'when there is a protocol specified' do
|
379
480
|
|
380
|
-
|
381
|
-
'https://myhost:8080'
|
382
|
-
end
|
481
|
+
context 'when credentials are specified \'http://USERNAME:PASSWORD@myhost:8080\'' do
|
383
482
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
483
|
+
let(:host) do
|
484
|
+
'http://USERNAME:PASSWORD@myhost:8080'
|
485
|
+
end
|
486
|
+
|
487
|
+
it 'extracts the credentials' do
|
488
|
+
expect(hosts[0][:user]).to eq('USERNAME')
|
489
|
+
expect(hosts[0][:password]).to eq('PASSWORD')
|
490
|
+
end
|
491
|
+
|
492
|
+
it 'extracts the host' do
|
493
|
+
expect(hosts[0][:host]).to eq('myhost')
|
494
|
+
end
|
495
|
+
|
496
|
+
it 'extracts the port' do
|
497
|
+
expect(hosts[0][:port]).to be(8080)
|
498
|
+
end
|
388
499
|
end
|
389
|
-
end
|
390
500
|
|
391
|
-
|
501
|
+
context 'when there is a trailing slash \'http://myhost/\'' do
|
392
502
|
|
393
|
-
|
394
|
-
|
503
|
+
let(:host) do
|
504
|
+
'http://myhost/'
|
505
|
+
end
|
506
|
+
|
507
|
+
it 'extracts the host' do
|
508
|
+
expect(hosts[0][:host]).to eq('myhost')
|
509
|
+
expect(hosts[0][:scheme]).to eq('http')
|
510
|
+
expect(hosts[0][:path]).to eq('')
|
511
|
+
end
|
512
|
+
|
513
|
+
it 'extracts the scheme' do
|
514
|
+
expect(hosts[0][:scheme]).to eq('http')
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'extracts the path' do
|
518
|
+
expect(hosts[0][:path]).to eq('')
|
519
|
+
end
|
395
520
|
end
|
396
521
|
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
522
|
+
context 'when there is a trailing slash with a path \'http://myhost/foo/bar/\'' do
|
523
|
+
|
524
|
+
let(:host) do
|
525
|
+
'http://myhost/foo/bar/'
|
526
|
+
end
|
527
|
+
|
528
|
+
it 'extracts the host' do
|
529
|
+
expect(hosts[0][:host]).to eq('myhost')
|
530
|
+
expect(hosts[0][:scheme]).to eq('http')
|
531
|
+
expect(hosts[0][:path]).to eq('/foo/bar')
|
532
|
+
end
|
403
533
|
end
|
404
|
-
end
|
405
534
|
|
406
|
-
|
535
|
+
context 'when the protocol is http' do
|
407
536
|
|
408
|
-
|
409
|
-
|
537
|
+
context 'when there is no port specified \'http://myhost\'' do
|
538
|
+
|
539
|
+
let(:host) do
|
540
|
+
'http://myhost'
|
541
|
+
end
|
542
|
+
|
543
|
+
it 'extracts the host' do
|
544
|
+
expect(hosts[0][:host]).to eq('myhost')
|
545
|
+
end
|
546
|
+
|
547
|
+
it 'extracts the protocol' do
|
548
|
+
expect(hosts[0][:protocol]).to eq('http')
|
549
|
+
end
|
550
|
+
|
551
|
+
it 'defaults to port 9200' do
|
552
|
+
expect(hosts[0][:port]).to be(9200)
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
context 'when there is a port specified \'http://myhost:7101\'' do
|
557
|
+
|
558
|
+
let(:host) do
|
559
|
+
'http://myhost:7101'
|
560
|
+
end
|
561
|
+
|
562
|
+
it 'extracts the host' do
|
563
|
+
expect(hosts[0][:host]).to eq('myhost')
|
564
|
+
end
|
565
|
+
|
566
|
+
it 'extracts the protocol' do
|
567
|
+
expect(hosts[0][:protocol]).to eq('http')
|
568
|
+
end
|
569
|
+
|
570
|
+
it 'extracts the port' do
|
571
|
+
expect(hosts[0][:port]).to be(7101)
|
572
|
+
end
|
573
|
+
|
574
|
+
context 'when there is a path specified \'http://myhost:7101/api\'' do
|
575
|
+
|
576
|
+
let(:host) do
|
577
|
+
'http://myhost:7101/api'
|
578
|
+
end
|
579
|
+
|
580
|
+
it 'sets the path' do
|
581
|
+
expect(hosts[0][:host]).to eq('myhost')
|
582
|
+
expect(hosts[0][:protocol]).to eq('http')
|
583
|
+
expect(hosts[0][:path]).to eq('/api')
|
584
|
+
expect(hosts[0][:port]).to be(7101)
|
585
|
+
end
|
586
|
+
|
587
|
+
it 'extracts the host' do
|
588
|
+
expect(hosts[0][:host]).to eq('myhost')
|
589
|
+
end
|
590
|
+
|
591
|
+
it 'extracts the protocol' do
|
592
|
+
expect(hosts[0][:protocol]).to eq('http')
|
593
|
+
end
|
594
|
+
|
595
|
+
it 'extracts the port' do
|
596
|
+
expect(hosts[0][:port]).to be(7101)
|
597
|
+
end
|
598
|
+
|
599
|
+
it 'extracts the path' do
|
600
|
+
expect(hosts[0][:path]).to eq('/api')
|
601
|
+
end
|
602
|
+
end
|
603
|
+
end
|
410
604
|
end
|
411
605
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
606
|
+
context 'when the protocol is https' do
|
607
|
+
|
608
|
+
context 'when there is no port specified \'https://myhost\'' do
|
609
|
+
|
610
|
+
let(:host) do
|
611
|
+
'https://myhost'
|
612
|
+
end
|
613
|
+
|
614
|
+
it 'extracts the host' do
|
615
|
+
expect(hosts[0][:host]).to eq('myhost')
|
616
|
+
end
|
617
|
+
|
618
|
+
it 'extracts the protocol' do
|
619
|
+
expect(hosts[0][:protocol]).to eq('https')
|
620
|
+
end
|
621
|
+
|
622
|
+
it 'defaults to port 443' do
|
623
|
+
expect(hosts[0][:port]).to be(443)
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
|
+
context 'when there is a port specified \'https://myhost:7101\'' do
|
628
|
+
|
629
|
+
let(:host) do
|
630
|
+
'https://myhost:7101'
|
631
|
+
end
|
632
|
+
|
633
|
+
it 'extracts the host' do
|
634
|
+
expect(hosts[0][:host]).to eq('myhost')
|
635
|
+
end
|
636
|
+
|
637
|
+
it 'extracts the protocol' do
|
638
|
+
expect(hosts[0][:protocol]).to eq('https')
|
639
|
+
end
|
640
|
+
|
641
|
+
it 'extracts the port' do
|
642
|
+
expect(hosts[0][:port]).to be(7101)
|
643
|
+
end
|
644
|
+
|
645
|
+
context 'when there is a path specified \'https://myhost:7101/api\'' do
|
646
|
+
|
647
|
+
let(:host) do
|
648
|
+
'https://myhost:7101/api'
|
649
|
+
end
|
650
|
+
|
651
|
+
it 'extracts the host' do
|
652
|
+
expect(hosts[0][:host]).to eq('myhost')
|
653
|
+
end
|
654
|
+
|
655
|
+
it 'extracts the protocol' do
|
656
|
+
expect(hosts[0][:protocol]).to eq('https')
|
657
|
+
end
|
658
|
+
|
659
|
+
it 'extracts the port' do
|
660
|
+
expect(hosts[0][:port]).to be(7101)
|
661
|
+
end
|
662
|
+
|
663
|
+
it 'extracts the path' do
|
664
|
+
expect(hosts[0][:path]).to eq('/api')
|
665
|
+
end
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
context 'when IPv6 format is used' do
|
670
|
+
|
671
|
+
around do |example|
|
672
|
+
original_setting = Faraday.ignore_env_proxy
|
673
|
+
Faraday.ignore_env_proxy = true
|
674
|
+
example.run
|
675
|
+
Faraday.ignore_env_proxy = original_setting
|
676
|
+
end
|
677
|
+
|
678
|
+
let(:host) do
|
679
|
+
'https://[2090:db8:85a3:9811::1f]:8080'
|
680
|
+
end
|
681
|
+
|
682
|
+
it 'extracts the host' do
|
683
|
+
expect(hosts[0][:host]).to eq('[2090:db8:85a3:9811::1f]')
|
684
|
+
end
|
685
|
+
|
686
|
+
it 'extracts the protocol' do
|
687
|
+
expect(hosts[0][:protocol]).to eq('https')
|
688
|
+
end
|
689
|
+
|
690
|
+
it 'extracts the port' do
|
691
|
+
expect(hosts[0][:port]).to be(8080)
|
692
|
+
end
|
693
|
+
|
694
|
+
it 'creates the correct full url' do
|
695
|
+
expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://[2090:db8:85a3:9811::1f]:8080')
|
696
|
+
end
|
697
|
+
end
|
416
698
|
end
|
417
699
|
end
|
418
700
|
|
419
|
-
context 'when
|
701
|
+
context 'when no protocol is specified \'myhost\'' do
|
420
702
|
|
421
703
|
let(:host) do
|
422
|
-
'
|
704
|
+
'myhost'
|
423
705
|
end
|
424
706
|
|
425
|
-
it '
|
707
|
+
it 'defaults to http' do
|
426
708
|
expect(hosts[0][:host]).to eq('myhost')
|
427
|
-
expect(hosts[0][:
|
428
|
-
|
709
|
+
expect(hosts[0][:protocol]).to eq('http')
|
710
|
+
end
|
711
|
+
|
712
|
+
it 'uses port 9200' do
|
713
|
+
expect(hosts[0][:port]).to be(9200)
|
429
714
|
end
|
430
715
|
end
|
431
716
|
end
|
432
717
|
|
433
|
-
context 'when the
|
718
|
+
context 'when the host is a Hash' do
|
434
719
|
|
435
720
|
let(:host) do
|
436
721
|
{ :host => 'myhost', :scheme => 'https' }
|
@@ -438,7 +723,13 @@ describe Elasticsearch::Transport::Client do
|
|
438
723
|
|
439
724
|
it 'extracts the host' do
|
440
725
|
expect(hosts[0][:host]).to eq('myhost')
|
441
|
-
|
726
|
+
end
|
727
|
+
|
728
|
+
it 'extracts the protocol' do
|
729
|
+
expect(hosts[0][:protocol]).to eq('https')
|
730
|
+
end
|
731
|
+
|
732
|
+
it 'extracts the port' do
|
442
733
|
expect(hosts[0][:port]).to be(9200)
|
443
734
|
end
|
444
735
|
|
@@ -497,7 +788,13 @@ describe Elasticsearch::Transport::Client do
|
|
497
788
|
|
498
789
|
it 'extracts the host' do
|
499
790
|
expect(hosts[0][:host]).to eq('myhost')
|
791
|
+
end
|
792
|
+
|
793
|
+
it 'extracts the protocol' do
|
500
794
|
expect(hosts[0][:scheme]).to eq('https')
|
795
|
+
end
|
796
|
+
|
797
|
+
it 'converts the port to an integer' do
|
501
798
|
expect(hosts[0][:port]).to be(443)
|
502
799
|
end
|
503
800
|
end
|
@@ -510,7 +807,13 @@ describe Elasticsearch::Transport::Client do
|
|
510
807
|
|
511
808
|
it 'extracts the host' do
|
512
809
|
expect(hosts[0][:host]).to eq('myhost')
|
810
|
+
end
|
811
|
+
|
812
|
+
it 'extracts the protocol' do
|
513
813
|
expect(hosts[0][:scheme]).to eq('https')
|
814
|
+
end
|
815
|
+
|
816
|
+
it 'extracts port as an integer' do
|
514
817
|
expect(hosts[0][:port]).to be(443)
|
515
818
|
end
|
516
819
|
end
|
@@ -524,7 +827,13 @@ describe Elasticsearch::Transport::Client do
|
|
524
827
|
|
525
828
|
it 'extracts the host' do
|
526
829
|
expect(hosts[0][:host]).to eq('myhost')
|
830
|
+
end
|
831
|
+
|
832
|
+
it 'extracts the protocol' do
|
527
833
|
expect(hosts[0][:scheme]).to eq('https')
|
834
|
+
end
|
835
|
+
|
836
|
+
it 'converts the port to an integer' do
|
528
837
|
expect(hosts[0][:port]).to be(9200)
|
529
838
|
end
|
530
839
|
|
@@ -536,7 +845,13 @@ describe Elasticsearch::Transport::Client do
|
|
536
845
|
|
537
846
|
it 'extracts the host' do
|
538
847
|
expect(hosts[0][:host]).to eq('myhost')
|
848
|
+
end
|
849
|
+
|
850
|
+
it 'extracts the protocol' do
|
539
851
|
expect(hosts[0][:scheme]).to eq('https')
|
852
|
+
end
|
853
|
+
|
854
|
+
it 'converts the port to an integer' do
|
540
855
|
expect(hosts[0][:port]).to be(443)
|
541
856
|
end
|
542
857
|
end
|
@@ -549,7 +864,13 @@ describe Elasticsearch::Transport::Client do
|
|
549
864
|
|
550
865
|
it 'extracts the host' do
|
551
866
|
expect(hosts[0][:host]).to eq('myhost')
|
867
|
+
end
|
868
|
+
|
869
|
+
it 'extracts the protocol' do
|
552
870
|
expect(hosts[0][:scheme]).to eq('https')
|
871
|
+
end
|
872
|
+
|
873
|
+
it 'extracts port as an integer' do
|
553
874
|
expect(hosts[0][:port]).to be(443)
|
554
875
|
end
|
555
876
|
end
|
@@ -565,7 +886,13 @@ describe Elasticsearch::Transport::Client do
|
|
565
886
|
|
566
887
|
it 'extracts the host' do
|
567
888
|
expect(hosts[0][:host]).to eq('myhost')
|
889
|
+
end
|
890
|
+
|
891
|
+
it 'extracts the protocol' do
|
568
892
|
expect(hosts[0][:protocol]).to eq('http')
|
893
|
+
end
|
894
|
+
|
895
|
+
it 'defaults to port 9200' do
|
569
896
|
expect(hosts[0][:port]).to be(9200)
|
570
897
|
end
|
571
898
|
end
|
@@ -578,20 +905,13 @@ describe Elasticsearch::Transport::Client do
|
|
578
905
|
|
579
906
|
it 'extracts the host' do
|
580
907
|
expect(hosts[0][:host]).to eq('myhost')
|
581
|
-
expect(hosts[0][:protocol]).to eq('http')
|
582
|
-
expect(hosts[0][:port]).to be(9200)
|
583
908
|
end
|
584
|
-
end
|
585
909
|
|
586
|
-
|
587
|
-
|
588
|
-
let(:host) do
|
589
|
-
['http://myhost']
|
910
|
+
it 'extracts the protocol' do
|
911
|
+
expect(hosts[0][:scheme]).to eq('http')
|
590
912
|
end
|
591
913
|
|
592
|
-
it '
|
593
|
-
expect(hosts[0][:host]).to eq('myhost')
|
594
|
-
expect(hosts[0][:protocol]).to eq('http')
|
914
|
+
it 'defaults to port 9200' do
|
595
915
|
expect(hosts[0][:port]).to be(9200)
|
596
916
|
end
|
597
917
|
end
|
@@ -616,7 +936,7 @@ describe Elasticsearch::Transport::Client do
|
|
616
936
|
end
|
617
937
|
end
|
618
938
|
|
619
|
-
context 'when there is one host with a
|
939
|
+
context 'when there is one host with a protocol and no port' do
|
620
940
|
|
621
941
|
let(:host) do
|
622
942
|
['https://myhost']
|
@@ -624,12 +944,18 @@ describe Elasticsearch::Transport::Client do
|
|
624
944
|
|
625
945
|
it 'extracts the host' do
|
626
946
|
expect(hosts[0][:host]).to eq('myhost')
|
627
|
-
|
628
|
-
|
947
|
+
end
|
948
|
+
|
949
|
+
it 'extracts the protocol' do
|
950
|
+
expect(hosts[0][:scheme]).to eq('https')
|
951
|
+
end
|
952
|
+
|
953
|
+
it 'defaults to port 443' do
|
954
|
+
expect(hosts[0][:port]).to be(443)
|
629
955
|
end
|
630
956
|
end
|
631
957
|
|
632
|
-
context 'when there is one host with a
|
958
|
+
context 'when there is one host with a protocol, path, and no port' do
|
633
959
|
|
634
960
|
let(:host) do
|
635
961
|
['http://myhost/foo/bar']
|
@@ -637,9 +963,18 @@ describe Elasticsearch::Transport::Client do
|
|
637
963
|
|
638
964
|
it 'extracts the host' do
|
639
965
|
expect(hosts[0][:host]).to eq('myhost')
|
640
|
-
|
966
|
+
end
|
967
|
+
|
968
|
+
it 'extracts the protocol' do
|
969
|
+
expect(hosts[0][:scheme]).to eq('http')
|
970
|
+
end
|
971
|
+
|
972
|
+
it 'defaults to port 9200' do
|
641
973
|
expect(hosts[0][:port]).to be(9200)
|
642
|
-
|
974
|
+
end
|
975
|
+
|
976
|
+
it 'extracts the path' do
|
977
|
+
expect(hosts[0][:path]).to eq('/foo/bar')
|
643
978
|
end
|
644
979
|
end
|
645
980
|
|
@@ -649,7 +984,7 @@ describe Elasticsearch::Transport::Client do
|
|
649
984
|
['host1', 'host2']
|
650
985
|
end
|
651
986
|
|
652
|
-
it 'extracts the
|
987
|
+
it 'extracts the hosts' do
|
653
988
|
expect(hosts[0][:host]).to eq('host1')
|
654
989
|
expect(hosts[0][:protocol]).to eq('http')
|
655
990
|
expect(hosts[0][:port]).to be(9200)
|
@@ -665,7 +1000,7 @@ describe Elasticsearch::Transport::Client do
|
|
665
1000
|
['host1:1000', 'host2:2000']
|
666
1001
|
end
|
667
1002
|
|
668
|
-
it 'extracts the
|
1003
|
+
it 'extracts the hosts' do
|
669
1004
|
expect(hosts[0][:host]).to eq('host1')
|
670
1005
|
expect(hosts[0][:protocol]).to eq('http')
|
671
1006
|
expect(hosts[0][:port]).to be(1000)
|
@@ -1055,10 +1390,130 @@ describe Elasticsearch::Transport::Client do
|
|
1055
1390
|
expect(request).to be(true)
|
1056
1391
|
end
|
1057
1392
|
end
|
1393
|
+
|
1394
|
+
context 'when x-opaque-id is set' do
|
1395
|
+
let(:client) { described_class.new(host: hosts) }
|
1396
|
+
|
1397
|
+
it 'uses x-opaque-id on a request' do
|
1398
|
+
expect(client.perform_request('GET', '/', { opaque_id: '12345' }).headers['x-opaque-id']).to eq('12345')
|
1399
|
+
end
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
context 'when an x-opaque-id prefix is set on initialization' do
|
1403
|
+
let(:prefix) { 'elastic_cloud' }
|
1404
|
+
let(:client) do
|
1405
|
+
described_class.new(host: hosts, opaque_id_prefix: prefix)
|
1406
|
+
end
|
1407
|
+
|
1408
|
+
it 'uses x-opaque-id on a request' do
|
1409
|
+
expect(client.perform_request('GET', '/', { opaque_id: '12345' }).headers['x-opaque-id']).to eq("#{prefix}12345")
|
1410
|
+
end
|
1411
|
+
|
1412
|
+
context 'when using an API call' do
|
1413
|
+
let(:client) { described_class.new(host: hosts) }
|
1414
|
+
|
1415
|
+
it 'doesnae raise an ArgumentError' do
|
1416
|
+
expect { client.perform_request('GET', '_search', opaque_id: 'no_error') }.not_to raise_error
|
1417
|
+
end
|
1418
|
+
|
1419
|
+
it 'uses X-Opaque-Id in the header' do
|
1420
|
+
allow(client).to receive(:perform_request) { OpenStruct.new(body: '') }
|
1421
|
+
expect { client.perform_request('GET', '_search', {}, nil, opaque_id: 'opaque_id') }.not_to raise_error
|
1422
|
+
expect(client).to have_received(:perform_request)
|
1423
|
+
.with('GET', '_search', {}, nil, { opaque_id: 'opaque_id' })
|
1424
|
+
end
|
1425
|
+
end
|
1426
|
+
end
|
1427
|
+
|
1428
|
+
context 'when using the API Compatibility Header' do
|
1429
|
+
it 'sets the API compatibility headers' do
|
1430
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = 'true'
|
1431
|
+
client = described_class.new(host: hosts)
|
1432
|
+
headers = client.transport.connections.first.connection.headers
|
1433
|
+
|
1434
|
+
expect(headers['Content-Type']).to eq('application/vnd.elasticsearch+json; compatible-with=7')
|
1435
|
+
expect(headers['Accept']).to eq('application/vnd.elasticsearch+json; compatible-with=7')
|
1436
|
+
|
1437
|
+
ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
|
1438
|
+
end
|
1439
|
+
|
1440
|
+
it 'does not use API compatibility headers' do
|
1441
|
+
val = ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
|
1442
|
+
client = described_class.new(host: hosts)
|
1443
|
+
expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
|
1444
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = val
|
1445
|
+
end
|
1446
|
+
|
1447
|
+
it 'does not use API compatibility headers when it is set to unsupported values' do
|
1448
|
+
val = ENV.delete('ELASTIC_CLIENT_APIVERSIONING')
|
1449
|
+
|
1450
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = 'test'
|
1451
|
+
client = described_class.new(host: hosts)
|
1452
|
+
expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
|
1453
|
+
|
1454
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = 'false'
|
1455
|
+
client = described_class.new(host: hosts)
|
1456
|
+
expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
|
1457
|
+
|
1458
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = '3'
|
1459
|
+
client = described_class.new(host: hosts)
|
1460
|
+
expect(client.transport.connections.first.connection.headers['Content-Type']).to eq('application/json')
|
1461
|
+
ENV['ELASTIC_CLIENT_APIVERSIONING'] = val
|
1462
|
+
end
|
1463
|
+
end
|
1464
|
+
|
1465
|
+
context 'when Elasticsearch response includes a warning header' do
|
1466
|
+
let(:logger) { double('logger', warn: '', warn?: '', info?: '', info: '', debug?: '', debug: '') }
|
1467
|
+
let(:client) do
|
1468
|
+
Elasticsearch::Transport::Client.new(hosts: hosts, logger: logger)
|
1469
|
+
end
|
1470
|
+
|
1471
|
+
let(:warning) { 'Elasticsearch warning: "deprecation warning"' }
|
1472
|
+
|
1473
|
+
it 'prints a warning' do
|
1474
|
+
expect_any_instance_of(Faraday::Connection).to receive(:run_request) do
|
1475
|
+
Elasticsearch::Transport::Transport::Response.new(200, {}, { 'warning' => warning })
|
1476
|
+
end
|
1477
|
+
client.perform_request('GET', '/')
|
1478
|
+
expect(logger).to have_received(:warn).with(warning)
|
1479
|
+
end
|
1480
|
+
end
|
1481
|
+
|
1482
|
+
context 'when a header is set on an endpoint request' do
|
1483
|
+
let(:client) { described_class.new(host: hosts) }
|
1484
|
+
let(:headers) { { 'user-agent' => 'my ruby app' } }
|
1485
|
+
|
1486
|
+
it 'performs the request with the header' do
|
1487
|
+
allow(client).to receive(:perform_request) { OpenStruct.new(body: '') }
|
1488
|
+
expect { client.perform_request('GET', '_search', {}, nil, headers) }.not_to raise_error
|
1489
|
+
expect(client).to have_received(:perform_request)
|
1490
|
+
.with('GET', '_search', {}, nil, headers)
|
1491
|
+
end
|
1492
|
+
end
|
1493
|
+
|
1494
|
+
context 'when a header is set on an endpoint request and on initialization' do
|
1495
|
+
let!(:client) do
|
1496
|
+
described_class.new(
|
1497
|
+
host: hosts,
|
1498
|
+
transport_options: { headers: instance_headers }
|
1499
|
+
)
|
1500
|
+
end
|
1501
|
+
let(:instance_headers) { { set_in_instantiation: 'header value' } }
|
1502
|
+
let(:param_headers) { {'user-agent' => 'My Ruby Tests', 'set-on-method-call' => 'header value'} }
|
1503
|
+
|
1504
|
+
it 'performs the request with the header' do
|
1505
|
+
expected_headers = client.transport.connections.connections.first.connection.headers.merge(param_headers)
|
1506
|
+
|
1507
|
+
expect_any_instance_of(Faraday::Connection)
|
1508
|
+
.to receive(:run_request)
|
1509
|
+
.with(:get, "http://#{hosts[0]}/_search", nil, expected_headers) { OpenStruct.new(body: '')}
|
1510
|
+
|
1511
|
+
client.perform_request('GET', '_search', {}, nil, param_headers)
|
1512
|
+
end
|
1513
|
+
end
|
1058
1514
|
end
|
1059
1515
|
|
1060
1516
|
context 'when the client connects to Elasticsearch' do
|
1061
|
-
|
1062
1517
|
let(:logger) do
|
1063
1518
|
Logger.new(STDERR).tap do |logger|
|
1064
1519
|
logger.formatter = proc do |severity, datetime, progname, msg|
|
@@ -1090,7 +1545,6 @@ describe Elasticsearch::Transport::Client do
|
|
1090
1545
|
end
|
1091
1546
|
|
1092
1547
|
context 'when a request is made' do
|
1093
|
-
|
1094
1548
|
let!(:response) do
|
1095
1549
|
client.perform_request('GET', '_cluster/health')
|
1096
1550
|
end
|
@@ -1101,9 +1555,7 @@ describe Elasticsearch::Transport::Client do
|
|
1101
1555
|
end
|
1102
1556
|
|
1103
1557
|
describe '#initialize' do
|
1104
|
-
|
1105
1558
|
context 'when options are specified' do
|
1106
|
-
|
1107
1559
|
let(:transport_options) do
|
1108
1560
|
{ headers: { accept: 'application/yaml', content_type: 'application/yaml' } }
|
1109
1561
|
end
|
@@ -1119,9 +1571,8 @@ describe Elasticsearch::Transport::Client do
|
|
1119
1571
|
end
|
1120
1572
|
|
1121
1573
|
context 'when a block is provided' do
|
1122
|
-
|
1123
1574
|
let(:client) do
|
1124
|
-
|
1575
|
+
described_class.new(host: ELASTICSEARCH_HOSTS.first, logger: logger) do |client|
|
1125
1576
|
client.headers['Accept'] = 'application/yaml'
|
1126
1577
|
end
|
1127
1578
|
end
|
@@ -1136,15 +1587,14 @@ describe Elasticsearch::Transport::Client do
|
|
1136
1587
|
end
|
1137
1588
|
|
1138
1589
|
context 'when the Faraday adapter is set in the block' do
|
1139
|
-
|
1140
1590
|
let(:client) do
|
1141
|
-
|
1591
|
+
described_class.new(host: ELASTICSEARCH_HOSTS.first, logger: logger) do |client|
|
1142
1592
|
client.adapter(:net_http_persistent)
|
1143
1593
|
end
|
1144
1594
|
end
|
1145
1595
|
|
1146
|
-
let(:
|
1147
|
-
client.transport.connections.first.connection.builder.
|
1596
|
+
let(:handler_name) do
|
1597
|
+
client.transport.connections.first.connection.builder.adapter.name
|
1148
1598
|
end
|
1149
1599
|
|
1150
1600
|
let(:response) do
|
@@ -1152,7 +1602,7 @@ describe Elasticsearch::Transport::Client do
|
|
1152
1602
|
end
|
1153
1603
|
|
1154
1604
|
it 'sets the adapter' do
|
1155
|
-
expect(
|
1605
|
+
expect(handler_name).to eq('Faraday::Adapter::NetHttpPersistent')
|
1156
1606
|
end
|
1157
1607
|
|
1158
1608
|
it 'uses the adapter to connect' do
|
@@ -1202,7 +1652,30 @@ describe Elasticsearch::Transport::Client do
|
|
1202
1652
|
expect(client.perform_request('GET', '_nodes/_local'))
|
1203
1653
|
expect {
|
1204
1654
|
client.perform_request('GET', '_nodes/_local')
|
1205
|
-
}.to raise_exception(Faraday::
|
1655
|
+
}.to raise_exception(Faraday::ConnectionFailed)
|
1656
|
+
end
|
1657
|
+
end
|
1658
|
+
|
1659
|
+
context 'when retry_on_failure is true and delay_on_retry is specified' do
|
1660
|
+
context 'when a node is unreachable' do
|
1661
|
+
let(:hosts) do
|
1662
|
+
[ELASTICSEARCH_HOSTS.first, "foobar1", "foobar2"]
|
1663
|
+
end
|
1664
|
+
|
1665
|
+
let(:options) do
|
1666
|
+
{ retry_on_failure: true, delay_on_retry: 3000 }
|
1667
|
+
end
|
1668
|
+
|
1669
|
+
let(:responses) do
|
1670
|
+
5.times.collect do
|
1671
|
+
client.perform_request('GET', '_nodes/_local')
|
1672
|
+
end
|
1673
|
+
end
|
1674
|
+
|
1675
|
+
it 'retries on failure' do
|
1676
|
+
allow_any_instance_of(Object).to receive(:sleep).with(3000 / 1000)
|
1677
|
+
expect(responses.all? { true }).to be(true)
|
1678
|
+
end
|
1206
1679
|
end
|
1207
1680
|
end
|
1208
1681
|
|
@@ -1265,7 +1738,7 @@ describe Elasticsearch::Transport::Client do
|
|
1265
1738
|
end
|
1266
1739
|
|
1267
1740
|
it 'sets the Accept-Encoding header' do
|
1268
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1741
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1269
1742
|
end
|
1270
1743
|
|
1271
1744
|
it 'preserves the other headers' do
|
@@ -1276,7 +1749,7 @@ describe Elasticsearch::Transport::Client do
|
|
1276
1749
|
context 'when using the HTTPClient adapter' do
|
1277
1750
|
|
1278
1751
|
let(:client) do
|
1279
|
-
described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :httpclient)
|
1752
|
+
described_class.new(hosts: ELASTICSEARCH_HOSTS, compression: true, adapter: :httpclient, enable_meta_header: false)
|
1280
1753
|
end
|
1281
1754
|
|
1282
1755
|
it 'compresses the request and decompresses the response' do
|
@@ -1284,7 +1757,7 @@ describe Elasticsearch::Transport::Client do
|
|
1284
1757
|
end
|
1285
1758
|
|
1286
1759
|
it 'sets the Accept-Encoding header' do
|
1287
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1760
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1288
1761
|
end
|
1289
1762
|
|
1290
1763
|
it 'preserves the other headers' do
|
@@ -1303,7 +1776,7 @@ describe Elasticsearch::Transport::Client do
|
|
1303
1776
|
end
|
1304
1777
|
|
1305
1778
|
it 'sets the Accept-Encoding header' do
|
1306
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1779
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1307
1780
|
end
|
1308
1781
|
|
1309
1782
|
it 'preserves the other headers' do
|
@@ -1322,7 +1795,7 @@ describe Elasticsearch::Transport::Client do
|
|
1322
1795
|
end
|
1323
1796
|
|
1324
1797
|
it 'sets the Accept-Encoding header' do
|
1325
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1798
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1326
1799
|
end
|
1327
1800
|
|
1328
1801
|
it 'preserves the other headers' do
|
@@ -1341,22 +1814,23 @@ describe Elasticsearch::Transport::Client do
|
|
1341
1814
|
end
|
1342
1815
|
|
1343
1816
|
it 'sets the Accept-Encoding header' do
|
1344
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1817
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1345
1818
|
end
|
1346
1819
|
|
1347
1820
|
it 'preserves the other headers' do
|
1348
1821
|
expect(client.transport.connections[0].connection.headers['User-Agent'])
|
1349
1822
|
end
|
1350
|
-
end
|
1823
|
+
end unless jruby?
|
1351
1824
|
end
|
1352
1825
|
end
|
1353
1826
|
|
1354
1827
|
context 'when using Curb as the transport', unless: jruby? do
|
1355
|
-
|
1356
1828
|
let(:client) do
|
1357
|
-
described_class.new(
|
1358
|
-
|
1359
|
-
|
1829
|
+
described_class.new(
|
1830
|
+
hosts: ELASTICSEARCH_HOSTS,
|
1831
|
+
compression: true,
|
1832
|
+
transport_class: Elasticsearch::Transport::Transport::HTTP::Curb
|
1833
|
+
)
|
1360
1834
|
end
|
1361
1835
|
|
1362
1836
|
it 'compresses the request and decompresses the response' do
|
@@ -1364,7 +1838,7 @@ describe Elasticsearch::Transport::Client do
|
|
1364
1838
|
end
|
1365
1839
|
|
1366
1840
|
it 'sets the Accept-Encoding header' do
|
1367
|
-
expect(client.transport.connections[0].connection.headers['Accept-Encoding'])
|
1841
|
+
expect(client.transport.connections[0].connection.headers['Accept-Encoding']).to eq 'gzip'
|
1368
1842
|
end
|
1369
1843
|
|
1370
1844
|
it 'preserves the other headers' do
|
@@ -1373,7 +1847,6 @@ describe Elasticsearch::Transport::Client do
|
|
1373
1847
|
end
|
1374
1848
|
|
1375
1849
|
context 'when using Manticore as the transport', if: jruby? do
|
1376
|
-
|
1377
1850
|
let(:client) do
|
1378
1851
|
described_class.new(hosts: ELASTICSEARCH_HOSTS,
|
1379
1852
|
compression: true,
|
@@ -1387,9 +1860,7 @@ describe Elasticsearch::Transport::Client do
|
|
1387
1860
|
end
|
1388
1861
|
|
1389
1862
|
describe '#perform_request' do
|
1390
|
-
|
1391
1863
|
context 'when a request is made' do
|
1392
|
-
|
1393
1864
|
before do
|
1394
1865
|
client.perform_request('DELETE', '_all')
|
1395
1866
|
client.perform_request('DELETE', 'myindex') rescue
|
@@ -1412,7 +1883,6 @@ describe Elasticsearch::Transport::Client do
|
|
1412
1883
|
end
|
1413
1884
|
|
1414
1885
|
context 'when an invalid url is specified' do
|
1415
|
-
|
1416
1886
|
it 'raises an exception' do
|
1417
1887
|
expect {
|
1418
1888
|
client.perform_request('GET', 'myindex/mydoc/1?routing=FOOBARBAZ')
|
@@ -1421,7 +1891,6 @@ describe Elasticsearch::Transport::Client do
|
|
1421
1891
|
end
|
1422
1892
|
|
1423
1893
|
context 'when the \'ignore\' parameter is specified' do
|
1424
|
-
|
1425
1894
|
let(:response) do
|
1426
1895
|
client.perform_request('PUT', '_foobar', ignore: 400)
|
1427
1896
|
end
|
@@ -1437,7 +1906,6 @@ describe Elasticsearch::Transport::Client do
|
|
1437
1906
|
end
|
1438
1907
|
|
1439
1908
|
context 'when request headers are specified' do
|
1440
|
-
|
1441
1909
|
let(:response) do
|
1442
1910
|
client.perform_request('GET', '/', {}, nil, { 'Content-Type' => 'application/yaml' })
|
1443
1911
|
end
|
@@ -1448,9 +1916,7 @@ describe Elasticsearch::Transport::Client do
|
|
1448
1916
|
end
|
1449
1917
|
|
1450
1918
|
describe 'selector' do
|
1451
|
-
|
1452
1919
|
context 'when the round-robin selector is used' do
|
1453
|
-
|
1454
1920
|
let(:nodes) do
|
1455
1921
|
3.times.collect do
|
1456
1922
|
client.perform_request('GET', '_nodes/_local').body['nodes'].to_a[0][1]['name']
|
@@ -1458,7 +1924,7 @@ describe Elasticsearch::Transport::Client do
|
|
1458
1924
|
end
|
1459
1925
|
|
1460
1926
|
let(:node_names) do
|
1461
|
-
client.
|
1927
|
+
client.perform_request('GET', '_nodes/stats').body('nodes').collect do |name, stats|
|
1462
1928
|
stats['name']
|
1463
1929
|
end
|
1464
1930
|
end
|
@@ -1477,7 +1943,6 @@ describe Elasticsearch::Transport::Client do
|
|
1477
1943
|
end
|
1478
1944
|
|
1479
1945
|
context 'when patron is used as an adapter', unless: jruby? do
|
1480
|
-
|
1481
1946
|
before do
|
1482
1947
|
require 'patron'
|
1483
1948
|
end
|
@@ -1486,12 +1951,39 @@ describe Elasticsearch::Transport::Client do
|
|
1486
1951
|
{ adapter: :patron }
|
1487
1952
|
end
|
1488
1953
|
|
1489
|
-
let(:
|
1490
|
-
client.transport.connections.first.connection.builder.
|
1954
|
+
let(:adapter) do
|
1955
|
+
client.transport.connections.first.connection.builder.adapter
|
1956
|
+
end
|
1957
|
+
|
1958
|
+
it 'uses the patron connection handler' do
|
1959
|
+
expect(adapter).to eq('Faraday::Adapter::Patron')
|
1960
|
+
end
|
1961
|
+
|
1962
|
+
it 'keeps connections open' do
|
1963
|
+
response = client.perform_request('GET', '_nodes/stats/http')
|
1964
|
+
connections_before = response.body['nodes'].values.find { |n| n['name'] == node_names.first }['http']['total_opened']
|
1965
|
+
client.transport.reload_connections!
|
1966
|
+
response = client.perform_request('GET', '_nodes/stats/http')
|
1967
|
+
connections_after = response.body['nodes'].values.find { |n| n['name'] == node_names.first }['http']['total_opened']
|
1968
|
+
expect(connections_after).to be >= (connections_before)
|
1969
|
+
end
|
1970
|
+
end
|
1971
|
+
|
1972
|
+
context 'when typhoeus is used as an adapter', unless: jruby? do
|
1973
|
+
before do
|
1974
|
+
require 'typhoeus'
|
1975
|
+
end
|
1976
|
+
|
1977
|
+
let(:options) do
|
1978
|
+
{ adapter: :typhoeus }
|
1979
|
+
end
|
1980
|
+
|
1981
|
+
let(:adapter) do
|
1982
|
+
client.transport.connections.first.connection.builder.adapter
|
1491
1983
|
end
|
1492
1984
|
|
1493
1985
|
it 'uses the patron connection handler' do
|
1494
|
-
expect(
|
1986
|
+
expect(adapter).to eq('Faraday::Adapter::Typhoeus')
|
1495
1987
|
end
|
1496
1988
|
|
1497
1989
|
it 'keeps connections open' do
|
@@ -1505,4 +1997,76 @@ describe Elasticsearch::Transport::Client do
|
|
1505
1997
|
end
|
1506
1998
|
end
|
1507
1999
|
end
|
2000
|
+
|
2001
|
+
context 'CA Fingerprinting' do
|
2002
|
+
context 'when setting a ca_fingerprint' do
|
2003
|
+
after do
|
2004
|
+
File.delete('./certificate.crt')
|
2005
|
+
File.delete('./certificate.key')
|
2006
|
+
end
|
2007
|
+
|
2008
|
+
let(:certificate) do
|
2009
|
+
system(
|
2010
|
+
'openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -subj "/C=BE/O=Test/CN=Test"' \
|
2011
|
+
' -keyout certificate.key -out certificate.crt',
|
2012
|
+
err: File::NULL
|
2013
|
+
)
|
2014
|
+
OpenSSL::X509::Certificate.new File.read('./certificate.crt')
|
2015
|
+
end
|
2016
|
+
|
2017
|
+
let(:client) do
|
2018
|
+
Elasticsearch::Transport::Client.new(
|
2019
|
+
host: 'https://elastic:changeme@localhost:9200',
|
2020
|
+
ca_fingerprint: OpenSSL::Digest::SHA256.hexdigest(certificate.to_der)
|
2021
|
+
)
|
2022
|
+
end
|
2023
|
+
|
2024
|
+
it 'validates CA fingerprints on perform request' do
|
2025
|
+
expect(client.transport.connections.connections.map(&:verified).uniq).to eq [false]
|
2026
|
+
allow(client.transport).to receive(:perform_request) { 'Hello' }
|
2027
|
+
|
2028
|
+
server = double('server').as_null_object
|
2029
|
+
allow(TCPSocket).to receive(:new) { server }
|
2030
|
+
socket = double('socket')
|
2031
|
+
allow(OpenSSL::SSL::SSLSocket).to receive(:new) { socket }
|
2032
|
+
allow(socket).to receive(:connect) { nil }
|
2033
|
+
allow(socket).to receive(:peer_cert_chain) { [certificate] }
|
2034
|
+
|
2035
|
+
response = client.perform_request('GET', '/')
|
2036
|
+
expect(client.transport.connections.connections.map(&:verified).uniq).to eq [true]
|
2037
|
+
expect(response).to eq 'Hello'
|
2038
|
+
end
|
2039
|
+
end
|
2040
|
+
|
2041
|
+
context 'when using an http host' do
|
2042
|
+
let(:client) do
|
2043
|
+
Elasticsearch::Transport::Client.new(
|
2044
|
+
host: 'http://elastic:changeme@localhost:9200',
|
2045
|
+
ca_fingerprint: 'test'
|
2046
|
+
)
|
2047
|
+
end
|
2048
|
+
|
2049
|
+
it 'raises an error' do
|
2050
|
+
expect do
|
2051
|
+
client.perform_request('GET', '/')
|
2052
|
+
end.to raise_exception(Elasticsearch::Transport::Transport::Error)
|
2053
|
+
end
|
2054
|
+
end
|
2055
|
+
|
2056
|
+
context 'when not setting a ca_fingerprint' do
|
2057
|
+
let(:client) do
|
2058
|
+
Elasticsearch::Transport::Client.new(
|
2059
|
+
host: 'http://elastic:changeme@localhost:9200'
|
2060
|
+
)
|
2061
|
+
end
|
2062
|
+
|
2063
|
+
it 'has unvalidated connections' do
|
2064
|
+
allow(client).to receive(:validate_ca_fingerprints) { nil }
|
2065
|
+
allow(client.transport).to receive(:perform_request) { nil }
|
2066
|
+
|
2067
|
+
client.perform_request('GET', '/')
|
2068
|
+
expect(client).to_not have_received(:validate_ca_fingerprints)
|
2069
|
+
end
|
2070
|
+
end
|
2071
|
+
end
|
1508
2072
|
end
|