Skip to content

Extract transport #1347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 7, 2021
1 change: 0 additions & 1 deletion benchmarks/actions/002_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

require_relative '../lib/benchmarks'

Benchmarks.register \
Expand Down
1 change: 0 additions & 1 deletion elasticsearch-api/elasticsearch-api.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ Gem::Specification.new do |s|
s.add_development_dependency 'ansi'
s.add_development_dependency 'bundler'
s.add_development_dependency 'elasticsearch'
s.add_development_dependency 'elasticsearch-transport'
s.add_development_dependency 'minitest'
s.add_development_dependency 'minitest-reporters'
s.add_development_dependency 'mocha'
Expand Down
1 change: 0 additions & 1 deletion elasticsearch-api/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
require 'jbuilder'
require 'jsonify'
require 'elasticsearch'
require 'elasticsearch-transport'
require 'elasticsearch-api'

require 'ansi'
Expand Down
12 changes: 0 additions & 12 deletions elasticsearch-transport/lib/elasticsearch/transport.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,3 @@
require "elasticsearch/transport/redacted"

require "elasticsearch/transport/version"

module Elasticsearch
module Client

# A convenience wrapper for {::Elasticsearch::Transport::Client#initialize}.
#
def new(arguments={}, &block)
Elasticsearch::Transport::Client.new(arguments, &block)
end
extend self
end
end
78 changes: 10 additions & 68 deletions elasticsearch-transport/lib/elasticsearch/transport/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ class Client
# @since 7.0.0
DEFAULT_HOST = 'localhost:9200'.freeze

# The default port to use if connecting using a Cloud ID.
#
# @since 7.2.0
DEFAULT_CLOUD_PORT = 9243

# The default port to use if not otherwise specified.
#
# @since 7.2.0
Expand Down Expand Up @@ -118,18 +113,13 @@ class Client
# The default is false. Responses will automatically be inflated if they are compressed.
# If a custom transport object is used, it must handle the request compression and response inflation.
#
# @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key`
# joined by a colon as a String, or a hash with the `id` and `api_key` values.
# @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client.
# This will be prepended to the id you set before each request
# if you're using X-Opaque-Id
# @option enable_meta_header [Boolean] :enable_meta_header Enable sending the meta data header to Cloud.
# (Default: true)
#
# @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block
#
def initialize(arguments = {}, &block)
@options = arguments.each_with_object({}) { |(k, v), args| args[k.to_sym] = v }
@options = arguments.transform_keys(&:to_sym)
@arguments = @options
@arguments[:logger] ||= @arguments[:log] ? DEFAULT_LOGGER.call() : nil
@arguments[:tracer] ||= @arguments[:trace] ? DEFAULT_TRACER.call() : nil
Expand All @@ -139,21 +129,17 @@ def initialize(arguments = {}, &block)
@arguments[:randomize_hosts] ||= false
@arguments[:transport_options] ||= {}
@arguments[:http] ||= {}
@arguments[:enable_meta_header] = arguments.fetch(:enable_meta_header) { true }
@arguments[:enable_meta_header] = arguments.fetch(:enable_meta_header, true)
@options[:http] ||= {}

set_api_key if (@api_key = @arguments[:api_key])

@seeds = extract_cloud_creds(@arguments)
@seeds ||= __extract_hosts(@arguments[:hosts] ||
@arguments[:host] ||
@arguments[:url] ||
@arguments[:urls] ||
ENV['ELASTICSEARCH_URL'] ||
DEFAULT_HOST)
@hosts = __extract_hosts(@arguments[:hosts] ||
@arguments[:host] ||
@arguments[:url] ||
@arguments[:urls] ||
ENV['ELASTICSEARCH_URL'] ||
DEFAULT_HOST)

@send_get_body_as = @arguments[:send_get_body_as] || 'GET'
@opaque_id_prefix = @arguments[:opaque_id_prefix] || nil

if @arguments[:request_timeout]
@arguments[:transport_options][:request] = { timeout: @arguments[:request_timeout] }
Expand All @@ -166,38 +152,25 @@ def initialize(arguments = {}, &block)
@transport = if @transport_class == Transport::HTTP::Faraday
@arguments[:adapter] ||= __auto_detect_adapter
set_meta_header # from include MetaHeader
@transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
@transport_class.new(hosts: @hosts, options: @arguments) do |faraday|
faraday.adapter(@arguments[:adapter])
block&.call faraday
end
else
set_meta_header # from include MetaHeader
@transport_class.new(hosts: @seeds, options: @arguments)
@transport_class.new(hosts: @hosts, options: @arguments)
end
end
end

# Performs a request through delegation to {#transport}.
#
def perform_request(method, path, params = {}, body = nil, headers = nil)
method = @send_get_body_as if 'GET' == method && body
if (opaque_id = params.delete(:opaque_id))
headers = {} if headers.nil?
opaque_id = @opaque_id_prefix ? "#{@opaque_id_prefix}#{opaque_id}" : opaque_id
headers.merge!('X-Opaque-Id' => opaque_id)
end
transport.perform_request(method, path, params, body, headers)
end

private

def set_api_key
@api_key = __encode(@api_key) if @api_key.is_a? Hash
add_header('Authorization' => "ApiKey #{@api_key}")
@arguments.delete(:user)
@arguments.delete(:password)
end

def add_header(header)
headers = @arguments[:transport_options]&.[](:headers) || {}
headers.merge!(header)
Expand All @@ -206,30 +179,6 @@ def add_header(header)
)
end

def extract_cloud_creds(arguments)
return unless arguments[:cloud_id] && !arguments[:cloud_id].empty?

name = arguments[:cloud_id].split(':')[0]
cloud_url, elasticsearch_instance = Base64.decode64(arguments[:cloud_id].gsub("#{name}:", '')).split('$')

if cloud_url.include?(':')
url, port = cloud_url.split(':')
host = "#{elasticsearch_instance}.#{url}"
else
host = "#{elasticsearch_instance}.#{cloud_url}"
port = arguments[:port] || DEFAULT_CLOUD_PORT
end
[
{
scheme: 'https',
user: arguments[:user],
password: arguments[:password],
host: host,
port: port.to_i
}
]
end

# Normalizes and returns hosts configuration.
#
# Arrayifies the `hosts_config` argument and extracts `host` and `port` info from strings.
Expand Down Expand Up @@ -328,13 +277,6 @@ def __auto_detect_adapter
::Faraday.default_adapter
end
end

# Encode credentials for the Authorization Header
# Credentials is the base64 encoding of id and api_key joined by a colon
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
def __encode(api_key)
Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':'))
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@
it 'does not include the password in the logged string' do
expect(logger).not_to receive(:error).with(/secret_password/)
expect {
client.cluster.stats
client.perform_request('GET', '/_cluster/stats')
}.to raise_exception(Faraday::ConnectionFailed)
end

it 'replaces the password with the string \'REDACTED\'' do
expect(logger).to receive(:error).with(/REDACTED/)
expect {
client.cluster.stats
client.perform_request('GET', '/_cluster/stats')
}.to raise_exception(Faraday::ConnectionFailed)
end
end
Expand Down Expand Up @@ -93,7 +93,7 @@
end

it 'raises an exception' do
expect { client.info }.to raise_exception(Faraday::ConnectionFailed)
expect { client.perform_request('GET', '/info') }.to raise_exception(Faraday::ConnectionFailed)
end
end

Expand Down
Loading