Skip to content

Commit f4be407

Browse files
committed
[Gem] Fixes User-Agent code for Elasticsearch client
In the migration to 8.x, the user agent code was extracted into transport, since we're now using that library in other projects. So for the Elasticsearch Client, the user-agent would be reported as the one defined in elastic-transport. This code fixes the issue and brings back the user agent in the format that was being used in 7.x
1 parent 56d5fae commit f4be407

File tree

2 files changed

+99
-8
lines changed

2 files changed

+99
-8
lines changed

Diff for: elasticsearch/lib/elasticsearch.rb

+30-8
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,8 @@ def initialize(arguments = {}, &block)
4646
@warned = false
4747
@opaque_id_prefix = arguments[:opaque_id_prefix] || nil
4848
api_key(arguments) if arguments[:api_key]
49-
if arguments[:cloud_id]
50-
arguments[:hosts] = setup_cloud_host(
51-
arguments[:cloud_id],
52-
arguments[:user],
53-
arguments[:password],
54-
arguments[:port]
55-
)
56-
end
49+
setup_cloud(arguments) if arguments[:cloud_id]
50+
set_user_agent!(arguments) unless sent_user_agent?(arguments)
5751
@transport = Elastic::Transport::Client.new(arguments, &block)
5852
end
5953

@@ -139,6 +133,15 @@ def api_key(arguments)
139133
end
140134
end
141135

136+
def setup_cloud(arguments)
137+
arguments[:hosts] = setup_cloud_host(
138+
arguments[:cloud_id],
139+
arguments[:user],
140+
arguments[:password],
141+
arguments[:port]
142+
)
143+
end
144+
142145
# Encode credentials for the Authorization Header
143146
# Credentials is the base64 encoding of id and api_key joined by a colon
144147
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
@@ -149,6 +152,25 @@ def encode(api_key)
149152
def elasticsearch_validation_request
150153
@transport.perform_request('GET', '/')
151154
end
155+
156+
def sent_user_agent?(arguments)
157+
return unless (headers = arguments&.[](:transport_options)&.[](:headers))
158+
!!headers.keys.detect { |h| h =~ /user-?_?agent/ }
159+
end
160+
161+
def set_user_agent!(arguments)
162+
user_agent = [
163+
"elasticsearch-ruby/#{Elasticsearch::VERSION}",
164+
"elastic-transport-ruby/#{Elastic::Transport::VERSION}",
165+
"RUBY_VERSION: #{RUBY_VERSION}"
166+
]
167+
if RbConfig::CONFIG && RbConfig::CONFIG['host_os']
168+
user_agent << "#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase} #{RbConfig::CONFIG['target_cpu']}"
169+
end
170+
arguments[:transport_options] ||= {}
171+
arguments[:transport_options][:headers] ||= {}
172+
arguments[:transport_options][:headers].merge!({ user_agent: user_agent.join('; ')})
173+
end
152174
end
153175

154176
# Error class for when we detect an unsupported version of Elasticsearch

Diff for: elasticsearch/spec/unit/user_agent_spec.rb

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
require 'spec_helper'
18+
19+
describe Elasticsearch::Client do
20+
let(:user_agent) {
21+
"elasticsearch-ruby/#{Elasticsearch::VERSION}; elastic-transport-ruby/#{Elastic::Transport::VERSION}; RUBY_VERSION: #{RUBY_VERSION}; #{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase} #{RbConfig::CONFIG['target_cpu']}"
22+
}
23+
24+
context 'when no user-agent is set on initialization' do
25+
let(:client) { described_class.new }
26+
27+
it 'has the expected header' do
28+
expect(client.transport.options[:transport_options][:headers][:user_agent]).to eq user_agent
29+
end
30+
end
31+
32+
context 'when a header is specified on initialization' do
33+
let(:client) do
34+
described_class.new(
35+
transport_options: { headers: { 'X-Test-Header' => 'Test' } }
36+
)
37+
end
38+
39+
it 'has the expected header' do
40+
expect(client.transport.options[:transport_options][:headers][:user_agent]).to eq user_agent
41+
expect(client.transport.options[:transport_options][:headers]['X-Test-Header']).to eq 'Test'
42+
end
43+
end
44+
45+
context 'when other transport_options are specified on initialization' do
46+
let(:client) do
47+
described_class.new(
48+
transport_options: { params: { format: 'yaml' } }
49+
)
50+
end
51+
52+
it 'has the expected header' do
53+
expect(client.transport.options[:transport_options][:headers][:user_agent]).to eq user_agent
54+
expect(client.transport.options[:transport_options][:params][:format]).to eq 'yaml'
55+
end
56+
end
57+
58+
context 'when :user_agent is specified on initialization' do
59+
let(:client) do
60+
described_class.new(
61+
transport_options: { headers: { user_agent: 'TestApp' } }
62+
)
63+
end
64+
65+
it 'has the expected header' do
66+
expect(client.transport.options[:transport_options][:headers][:user_agent]).to eq 'TestApp'
67+
end
68+
end
69+
end

0 commit comments

Comments
 (0)