elasticsearch-transport 7.4.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 +184 -59
- 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 +107 -49
- 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 +64 -76
| @@ -1,6 +1,19 @@ | |
| 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 | 
             
            # coding: utf-8
         | 
| 6 19 | 
             
            lib = File.expand_path('../lib', __FILE__)
         | 
| @@ -8,74 +21,53 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) | |
| 8 21 | 
             
            require 'elasticsearch/transport/version'
         | 
| 9 22 |  | 
| 10 23 | 
             
            Gem::Specification.new do |s|
         | 
| 11 | 
            -
              s.name          =  | 
| 24 | 
            +
              s.name          = 'elasticsearch-transport'
         | 
| 12 25 | 
             
              s.version       = Elasticsearch::Transport::VERSION
         | 
| 13 | 
            -
              s.authors       = [ | 
| 14 | 
            -
              s.email         = [ | 
| 15 | 
            -
              s.summary       =  | 
| 16 | 
            -
              s.homepage      =  | 
| 17 | 
            -
              s.license       =  | 
| 18 | 
            -
             | 
| 26 | 
            +
              s.authors       = ['Karel Minarik']
         | 
| 27 | 
            +
              s.email         = ['karel.minarik@elasticsearch.org']
         | 
| 28 | 
            +
              s.summary       = 'Ruby client for Elasticsearch.'
         | 
| 29 | 
            +
              s.homepage      = 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.16/index.html'
         | 
| 30 | 
            +
              s.license       = 'Apache-2.0'
         | 
| 31 | 
            +
              s.metadata = {
         | 
| 32 | 
            +
                'homepage_uri' => 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.16/index.html',
         | 
| 33 | 
            +
                'changelog_uri' => 'https://github.com/elastic/elasticsearch-ruby/blob/7.16/CHANGELOG.md',
         | 
| 34 | 
            +
                'source_code_uri' => 'https://github.com/elastic/elasticsearch-ruby/tree/7.16/elasticsearch-transport',
         | 
| 35 | 
            +
                'bug_tracker_uri' => 'https://github.com/elastic/elasticsearch-ruby/issues'
         | 
| 36 | 
            +
              }
         | 
| 19 37 | 
             
              s.files         = `git ls-files`.split($/)
         | 
| 20 38 | 
             
              s.executables   = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
         | 
| 21 39 | 
             
              s.test_files    = s.files.grep(%r{^(test|spec|features)/})
         | 
| 22 | 
            -
              s.require_paths = [ | 
| 23 | 
            -
             | 
| 24 | 
            -
              s.extra_rdoc_files  = [ "README.md", "LICENSE" ]
         | 
| 25 | 
            -
              s.rdoc_options      = [ "--charset=UTF-8" ]
         | 
| 26 | 
            -
             | 
| 27 | 
            -
              s.required_ruby_version = '>= 1.9'
         | 
| 28 | 
            -
             | 
| 29 | 
            -
              s.add_dependency "multi_json"
         | 
| 30 | 
            -
              s.add_dependency "faraday"
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
         | 
| 33 | 
            -
                s.add_dependency "system_timer"
         | 
| 34 | 
            -
              end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
              s.add_development_dependency "bundler"
         | 
| 37 | 
            -
             | 
| 38 | 
            -
              if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
         | 
| 39 | 
            -
                s.add_development_dependency "rake", "~> 11.1"
         | 
| 40 | 
            -
              else
         | 
| 41 | 
            -
                s.add_development_dependency "rake", "< 11.0"
         | 
| 42 | 
            -
              end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
              s.add_development_dependency "ansi"
         | 
| 45 | 
            -
              s.add_development_dependency "shoulda-context"
         | 
| 46 | 
            -
              s.add_development_dependency "mocha"
         | 
| 47 | 
            -
              s.add_development_dependency "yard"
         | 
| 48 | 
            -
              s.add_development_dependency "pry"
         | 
| 40 | 
            +
              s.require_paths = ['lib']
         | 
| 49 41 |  | 
| 50 | 
            -
               | 
| 51 | 
            -
              s. | 
| 52 | 
            -
              s.add_development_dependency "patron" unless defined? JRUBY_VERSION
         | 
| 53 | 
            -
              s.add_development_dependency "typhoeus", '~> 0.6'
         | 
| 54 | 
            -
              s.add_development_dependency "net-http-persistent"
         | 
| 55 | 
            -
              s.add_development_dependency "httpclient"
         | 
| 56 | 
            -
              s.add_development_dependency "manticore", '~> 0.6' if defined? JRUBY_VERSION
         | 
| 57 | 
            -
              s.add_development_dependency "hashie"
         | 
| 42 | 
            +
              s.extra_rdoc_files  = [ 'README.md', 'LICENSE' ]
         | 
| 43 | 
            +
              s.rdoc_options      = [ '--charset=UTF-8' ]
         | 
| 58 44 |  | 
| 59 | 
            -
               | 
| 60 | 
            -
              if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
         | 
| 61 | 
            -
                s.add_development_dependency "test-unit", '~> 2'
         | 
| 62 | 
            -
                s.add_development_dependency "json", '~> 1.8'
         | 
| 63 | 
            -
              end
         | 
| 45 | 
            +
              s.required_ruby_version = '>= 2.4'
         | 
| 64 46 |  | 
| 65 | 
            -
               | 
| 66 | 
            -
             | 
| 67 | 
            -
                s.add_development_dependency "minitest-reporters"
         | 
| 68 | 
            -
                s.add_development_dependency "elasticsearch-extensions"
         | 
| 69 | 
            -
                s.add_development_dependency "ruby-prof"    unless defined?(JRUBY_VERSION) || defined?(Rubinius)
         | 
| 70 | 
            -
                s.add_development_dependency "require-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
         | 
| 71 | 
            -
                s.add_development_dependency "simplecov"
         | 
| 72 | 
            -
                s.add_development_dependency "simplecov-rcov"
         | 
| 73 | 
            -
                s.add_development_dependency "cane"
         | 
| 74 | 
            -
              end
         | 
| 47 | 
            +
              s.add_dependency 'multi_json'
         | 
| 48 | 
            +
              s.add_dependency 'faraday', '>= 1', '< 3'
         | 
| 75 49 |  | 
| 76 | 
            -
               | 
| 77 | 
            -
             | 
| 78 | 
            -
               | 
| 50 | 
            +
              # Faraday Adapters
         | 
| 51 | 
            +
              s.add_development_dependency 'manticore' if defined? JRUBY_VERSION
         | 
| 52 | 
            +
              s.add_development_dependency 'curb' unless defined? JRUBY_VERSION
         | 
| 53 | 
            +
              s.add_development_dependency 'ansi'
         | 
| 54 | 
            +
              s.add_development_dependency 'bundler'
         | 
| 55 | 
            +
              s.add_development_dependency 'cane'
         | 
| 56 | 
            +
              s.add_development_dependency 'elasticsearch', ['>= 7', '< 8.0.0']
         | 
| 57 | 
            +
              s.add_development_dependency 'elasticsearch-extensions'
         | 
| 58 | 
            +
              s.add_development_dependency 'hashie'
         | 
| 59 | 
            +
              s.add_development_dependency 'minitest'
         | 
| 60 | 
            +
              s.add_development_dependency 'minitest-reporters'
         | 
| 61 | 
            +
              s.add_development_dependency 'mocha'
         | 
| 62 | 
            +
              s.add_development_dependency 'patron' unless defined? JRUBY_VERSION
         | 
| 63 | 
            +
              s.add_development_dependency 'pry'
         | 
| 64 | 
            +
              s.add_development_dependency 'rake', '~> 13'
         | 
| 65 | 
            +
              s.add_development_dependency 'require-prof' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
         | 
| 66 | 
            +
              s.add_development_dependency 'ruby-prof'    unless defined?(JRUBY_VERSION) || defined?(Rubinius)
         | 
| 67 | 
            +
              s.add_development_dependency 'shoulda-context'
         | 
| 68 | 
            +
              s.add_development_dependency 'simplecov'
         | 
| 69 | 
            +
              s.add_development_dependency 'test-unit', '~> 2'
         | 
| 70 | 
            +
              s.add_development_dependency 'yard'
         | 
| 79 71 |  | 
| 80 72 | 
             
              s.description = <<-DESC.gsub(/^    /, '')
         | 
| 81 73 | 
             
                Ruby client for Elasticsearch. See the `elasticsearch` gem for full integration.
         | 
| @@ -1,18 +1,32 @@ | |
| 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 'base64'
         | 
| 19 | 
            +
            require 'elasticsearch/transport/meta_header'
         | 
| 6 20 |  | 
| 7 21 | 
             
            module Elasticsearch
         | 
| 8 22 | 
             
              module Transport
         | 
| 9 | 
            -
             | 
| 10 23 | 
             
                # Handles communication with an Elasticsearch cluster.
         | 
| 11 24 | 
             
                #
         | 
| 12 25 | 
             
                # See {file:README.md README} for usage and code examples.
         | 
| 13 26 | 
             
                #
         | 
| 14 27 | 
             
                class Client
         | 
| 15 | 
            -
                   | 
| 28 | 
            +
                  include MetaHeader
         | 
| 29 | 
            +
                  DEFAULT_TRANSPORT_CLASS = Transport::HTTP::Faraday
         | 
| 16 30 |  | 
| 17 31 | 
             
                  DEFAULT_LOGGER = lambda do
         | 
| 18 32 | 
             
                    require 'logger'
         | 
| @@ -36,9 +50,15 @@ module Elasticsearch | |
| 36 50 | 
             
                  DEFAULT_HOST = 'localhost:9200'.freeze
         | 
| 37 51 |  | 
| 38 52 | 
             
                  # The default port to use if connecting using a Cloud ID.
         | 
| 53 | 
            +
                  # Updated from 9243 to 443 in client version 7.10.1
         | 
| 39 54 | 
             
                  #
         | 
| 40 55 | 
             
                  # @since 7.2.0
         | 
| 41 | 
            -
                  DEFAULT_CLOUD_PORT =  | 
| 56 | 
            +
                  DEFAULT_CLOUD_PORT = 443
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  # The default port to use if not otherwise specified.
         | 
| 59 | 
            +
                  #
         | 
| 60 | 
            +
                  # @since 7.2.0
         | 
| 61 | 
            +
                  DEFAULT_PORT = 9200
         | 
| 42 62 |  | 
| 43 63 | 
             
                  # Returns the transport object.
         | 
| 44 64 | 
             
                  #
         | 
| @@ -72,6 +92,8 @@ module Elasticsearch | |
| 72 92 | 
             
                  #
         | 
| 73 93 | 
             
                  # @option arguments [Boolean,Number] :retry_on_failure   Retry X times when request fails before raising and
         | 
| 74 94 | 
             
                  #                                                        exception (false by default)
         | 
| 95 | 
            +
                  # @option arguments [Number] :delay_on_retry  Delay in milliseconds between each retry (0 by default)
         | 
| 96 | 
            +
                  #
         | 
| 75 97 | 
             
                  # @option arguments Array<Number> :retry_on_status Retry when specific status codes are returned
         | 
| 76 98 | 
             
                  #
         | 
| 77 99 | 
             
                  # @option arguments [Boolean] :reload_on_failure Reload connections after failure (false by default)
         | 
| @@ -99,6 +121,15 @@ module Elasticsearch | |
| 99 121 | 
             
                  #   The default is false. Responses will automatically be inflated if they are compressed.
         | 
| 100 122 | 
             
                  #   If a custom transport object is used, it must handle the request compression and response inflation.
         | 
| 101 123 | 
             
                  #
         | 
| 124 | 
            +
                  # @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key`
         | 
| 125 | 
            +
                  #                                         joined by a colon as a String, or a hash with the `id` and `api_key` values.
         | 
| 126 | 
            +
                  # @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client.
         | 
| 127 | 
            +
                  #                                                     This will be prepended to the id you set before each request
         | 
| 128 | 
            +
                  #                                                     if you're using X-Opaque-Id
         | 
| 129 | 
            +
                  # @option enable_meta_header [Boolean] :enable_meta_header Enable sending the meta data header to Cloud.
         | 
| 130 | 
            +
                  #                                                          (Default: true)
         | 
| 131 | 
            +
                  # @option ca_fingerprint [String] :ca_fingerprint provide this value to only trust certificates that are signed by a specific CA certificate
         | 
| 132 | 
            +
                  #
         | 
| 102 133 | 
             
                  # @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block
         | 
| 103 134 | 
             
                  #
         | 
| 104 135 | 
             
                  def initialize(arguments={}, &block)
         | 
| @@ -108,61 +139,140 @@ module Elasticsearch | |
| 108 139 | 
             
                    @arguments[:tracer] ||= @arguments[:trace] ? DEFAULT_TRACER.call() : nil
         | 
| 109 140 | 
             
                    @arguments[:reload_connections] ||= false
         | 
| 110 141 | 
             
                    @arguments[:retry_on_failure]   ||= false
         | 
| 142 | 
            +
                    @arguments[:delay_on_retry]     ||= 0
         | 
| 111 143 | 
             
                    @arguments[:reload_on_failure]  ||= false
         | 
| 112 144 | 
             
                    @arguments[:randomize_hosts]    ||= false
         | 
| 113 145 | 
             
                    @arguments[:transport_options]  ||= {}
         | 
| 114 146 | 
             
                    @arguments[:http]               ||= {}
         | 
| 115 | 
            -
                    @ | 
| 147 | 
            +
                    @arguments[:enable_meta_header] = arguments.fetch(:enable_meta_header) { true }
         | 
| 148 | 
            +
                    @options[:http]                 ||= {}
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                    set_api_key if (@api_key = @arguments[:api_key])
         | 
| 151 | 
            +
                    set_compatibility_header if ENV['ELASTIC_CLIENT_APIVERSIONING']
         | 
| 116 152 |  | 
| 117 153 | 
             
                    @seeds = extract_cloud_creds(@arguments)
         | 
| 118 154 | 
             
                    @seeds ||= __extract_hosts(@arguments[:hosts] ||
         | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 155 | 
            +
                                               @arguments[:host] ||
         | 
| 156 | 
            +
                                               @arguments[:url] ||
         | 
| 157 | 
            +
                                               @arguments[:urls] ||
         | 
| 158 | 
            +
                                               ENV['ELASTICSEARCH_URL'] ||
         | 
| 159 | 
            +
                                               DEFAULT_HOST)
         | 
| 124 160 |  | 
| 125 161 | 
             
                    @send_get_body_as = @arguments[:send_get_body_as] || 'GET'
         | 
| 162 | 
            +
                    @opaque_id_prefix = @arguments[:opaque_id_prefix] || nil
         | 
| 163 | 
            +
                    @ca_fingerprint = @arguments.delete(:ca_fingerprint)
         | 
| 126 164 |  | 
| 127 165 | 
             
                    if @arguments[:request_timeout]
         | 
| 128 | 
            -
                      @arguments[:transport_options][:request] = { : | 
| 166 | 
            +
                      @arguments[:transport_options][:request] = { timeout: @arguments[:request_timeout] }
         | 
| 129 167 | 
             
                    end
         | 
| 130 168 |  | 
| 131 169 | 
             
                    if @arguments[:transport]
         | 
| 132 170 | 
             
                      @transport = @arguments[:transport]
         | 
| 133 171 | 
             
                    else
         | 
| 134 | 
            -
                      transport_class | 
| 135 | 
            -
                      if transport_class == Transport::HTTP::Faraday
         | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 172 | 
            +
                      @transport_class = @arguments[:transport_class] || DEFAULT_TRANSPORT_CLASS
         | 
| 173 | 
            +
                      @transport = if @transport_class == Transport::HTTP::Faraday
         | 
| 174 | 
            +
                                     @arguments[:adapter] ||= __auto_detect_adapter
         | 
| 175 | 
            +
                                     set_meta_header # from include MetaHeader
         | 
| 176 | 
            +
                                     @transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
         | 
| 177 | 
            +
                                       faraday.adapter(@arguments[:adapter])
         | 
| 178 | 
            +
                                       block&.call faraday
         | 
| 179 | 
            +
                                     end
         | 
| 180 | 
            +
                                   else
         | 
| 181 | 
            +
                                     set_meta_header # from include MetaHeader
         | 
| 182 | 
            +
                                     @transport_class.new(hosts: @seeds, options: @arguments)
         | 
| 183 | 
            +
                                   end
         | 
| 145 184 | 
             
                    end
         | 
| 146 185 | 
             
                  end
         | 
| 147 186 |  | 
| 148 187 | 
             
                  # Performs a request through delegation to {#transport}.
         | 
| 149 188 | 
             
                  #
         | 
| 150 | 
            -
                  def perform_request(method, path, params={}, body=nil, headers=nil)
         | 
| 189 | 
            +
                  def perform_request(method, path, params = {}, body = nil, headers = nil)
         | 
| 151 190 | 
             
                    method = @send_get_body_as if 'GET' == method && body
         | 
| 191 | 
            +
                    if (opaque_id = params.delete(:opaque_id))
         | 
| 192 | 
            +
                      headers = {} if headers.nil?
         | 
| 193 | 
            +
                      opaque_id = @opaque_id_prefix ? "#{@opaque_id_prefix}#{opaque_id}" : opaque_id
         | 
| 194 | 
            +
                      headers.merge!('X-Opaque-Id' => opaque_id)
         | 
| 195 | 
            +
                    end
         | 
| 196 | 
            +
                    validate_ca_fingerprints if @ca_fingerprint
         | 
| 152 197 | 
             
                    transport.perform_request(method, path, params, body, headers)
         | 
| 153 198 | 
             
                  end
         | 
| 154 199 |  | 
| 155 200 | 
             
                  private
         | 
| 156 201 |  | 
| 202 | 
            +
                  def set_api_key
         | 
| 203 | 
            +
                    @api_key = __encode(@api_key) if @api_key.is_a? Hash
         | 
| 204 | 
            +
                    add_header('Authorization' => "ApiKey #{@api_key}")
         | 
| 205 | 
            +
                    @arguments.delete(:user)
         | 
| 206 | 
            +
                    @arguments.delete(:password)
         | 
| 207 | 
            +
                  end
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                  def set_compatibility_header
         | 
| 210 | 
            +
                    return unless ['1', 'true'].include?(ENV['ELASTIC_CLIENT_APIVERSIONING'])
         | 
| 211 | 
            +
                    return if instance_variable_get('@options').dig(:transport_options, :headers, 'Accept')
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                    add_header(
         | 
| 214 | 
            +
                      {
         | 
| 215 | 
            +
                        'Accept' => 'application/vnd.elasticsearch+json; compatible-with=7',
         | 
| 216 | 
            +
                        'Content-Type' => 'application/vnd.elasticsearch+json; compatible-with=7'
         | 
| 217 | 
            +
                      }
         | 
| 218 | 
            +
                    )
         | 
| 219 | 
            +
                  end
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                  def validate_ca_fingerprints
         | 
| 222 | 
            +
                    transport.connections.connections.each do |connection|
         | 
| 223 | 
            +
                      unless connection.host[:scheme] == 'https'
         | 
| 224 | 
            +
                        raise Elasticsearch::Transport::Transport::Error, 'CA fingerprinting can\'t be configured over http'
         | 
| 225 | 
            +
                      end
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                      next if connection.verified
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                      ctx = OpenSSL::SSL::SSLContext.new
         | 
| 230 | 
            +
                      socket = TCPSocket.new(connection.host[:host], connection.host[:port])
         | 
| 231 | 
            +
                      ssl = OpenSSL::SSL::SSLSocket.new(socket, ctx)
         | 
| 232 | 
            +
                      ssl.connect
         | 
| 233 | 
            +
                      cert_store = ssl.peer_cert_chain
         | 
| 234 | 
            +
                      matching_certs = cert_store.select do |cert|
         | 
| 235 | 
            +
                        OpenSSL::Digest::SHA256.hexdigest(cert.to_der).upcase == @ca_fingerprint.upcase.gsub(':', '')
         | 
| 236 | 
            +
                      end
         | 
| 237 | 
            +
                      if matching_certs.empty?
         | 
| 238 | 
            +
                        raise Elasticsearch::Transport::Transport::Error,
         | 
| 239 | 
            +
                              'Server certificate CA fingerprint does not match the value configured in ca_fingerprint'
         | 
| 240 | 
            +
                      end
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                      connection.verified = true
         | 
| 243 | 
            +
                    end
         | 
| 244 | 
            +
                  end
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                  def add_header(header)
         | 
| 247 | 
            +
                    headers = @arguments[:transport_options]&.[](:headers) || {}
         | 
| 248 | 
            +
                    headers.merge!(header)
         | 
| 249 | 
            +
                    @arguments[:transport_options].merge!(
         | 
| 250 | 
            +
                      headers: headers
         | 
| 251 | 
            +
                    )
         | 
| 252 | 
            +
                  end
         | 
| 253 | 
            +
             | 
| 157 254 | 
             
                  def extract_cloud_creds(arguments)
         | 
| 158 | 
            -
                    return unless arguments[:cloud_id]
         | 
| 255 | 
            +
                    return unless arguments[:cloud_id] && !arguments[:cloud_id].empty?
         | 
| 256 | 
            +
             | 
| 159 257 | 
             
                    name = arguments[:cloud_id].split(':')[0]
         | 
| 160 258 | 
             
                    cloud_url, elasticsearch_instance = Base64.decode64(arguments[:cloud_id].gsub("#{name}:", '')).split('$')
         | 
| 161 | 
            -
             | 
| 259 | 
            +
             | 
| 260 | 
            +
                    if cloud_url.include?(':')
         | 
| 261 | 
            +
                      url, port = cloud_url.split(':')
         | 
| 262 | 
            +
                      host = "#{elasticsearch_instance}.#{url}"
         | 
| 263 | 
            +
                    else
         | 
| 264 | 
            +
                      host = "#{elasticsearch_instance}.#{cloud_url}"
         | 
| 265 | 
            +
                      port = arguments[:port] || DEFAULT_CLOUD_PORT
         | 
| 266 | 
            +
                    end
         | 
| 267 | 
            +
                    [
         | 
| 268 | 
            +
                      {
         | 
| 269 | 
            +
                        scheme: 'https',
         | 
| 162 270 | 
             
                        user: arguments[:user],
         | 
| 163 271 | 
             
                        password: arguments[:password],
         | 
| 164 | 
            -
                        host:  | 
| 165 | 
            -
                        port:  | 
| 272 | 
            +
                        host: host,
         | 
| 273 | 
            +
                        port: port.to_i
         | 
| 274 | 
            +
                      }
         | 
| 275 | 
            +
                    ]
         | 
| 166 276 | 
             
                  end
         | 
| 167 277 |  | 
| 168 278 | 
             
                  # Normalizes and returns hosts configuration.
         | 
| @@ -195,39 +305,47 @@ module Elasticsearch | |
| 195 305 |  | 
| 196 306 | 
             
                  def __parse_host(host)
         | 
| 197 307 | 
             
                    host_parts = case host
         | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 221 | 
            -
             | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 308 | 
            +
                                 when String
         | 
| 309 | 
            +
                                   if host =~ /^[a-z]+\:\/\//
         | 
| 310 | 
            +
                                     # Construct a new `URI::Generic` directly from the array returned by URI::split.
         | 
| 311 | 
            +
                                     # This avoids `URI::HTTP` and `URI::HTTPS`, which supply default ports.
         | 
| 312 | 
            +
                                     uri = URI::Generic.new(*URI.split(host))
         | 
| 313 | 
            +
                                     default_port = uri.scheme == 'https' ? 443 : DEFAULT_PORT
         | 
| 314 | 
            +
                                     {
         | 
| 315 | 
            +
                                       scheme: uri.scheme,
         | 
| 316 | 
            +
                                       user: uri.user,
         | 
| 317 | 
            +
                                       password: uri.password,
         | 
| 318 | 
            +
                                       host: uri.host,
         | 
| 319 | 
            +
                                       path: uri.path,
         | 
| 320 | 
            +
                                       port: uri.port || default_port
         | 
| 321 | 
            +
                                     }
         | 
| 322 | 
            +
                                   else
         | 
| 323 | 
            +
                                     host, port = host.split(':')
         | 
| 324 | 
            +
                                     { host: host, port: port }
         | 
| 325 | 
            +
                                   end
         | 
| 326 | 
            +
                                 when URI
         | 
| 327 | 
            +
                                   {
         | 
| 328 | 
            +
                                     scheme: host.scheme,
         | 
| 329 | 
            +
                                     user: host.user,
         | 
| 330 | 
            +
                                     password: host.password,
         | 
| 331 | 
            +
                                     host: host.host,
         | 
| 332 | 
            +
                                     path: host.path,
         | 
| 333 | 
            +
                                     port: host.port
         | 
| 334 | 
            +
                                   }
         | 
| 335 | 
            +
                                 when Hash
         | 
| 336 | 
            +
                                   host
         | 
| 337 | 
            +
                                 else
         | 
| 338 | 
            +
                                   raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
         | 
| 339 | 
            +
                                 end
         | 
| 340 | 
            +
                    if @api_key
         | 
| 341 | 
            +
                      # Remove Basic Auth if using API KEY
         | 
| 342 | 
            +
                      host_parts.delete(:user)
         | 
| 343 | 
            +
                      host_parts.delete(:password)
         | 
| 224 344 | 
             
                    else
         | 
| 225 | 
            -
                       | 
| 345 | 
            +
                      @options[:http][:user] ||= host_parts[:user]
         | 
| 346 | 
            +
                      @options[:http][:password] ||= host_parts[:password]
         | 
| 226 347 | 
             
                    end
         | 
| 227 348 |  | 
| 228 | 
            -
                    @options[:http][:user] ||= host_parts[:user]
         | 
| 229 | 
            -
                    @options[:http][:password] ||= host_parts[:password]
         | 
| 230 | 
            -
             | 
| 231 349 | 
             
                    host_parts[:port] = host_parts[:port].to_i if host_parts[:port]
         | 
| 232 350 | 
             
                    host_parts[:path].chomp!('/') if host_parts[:path]
         | 
| 233 351 | 
             
                    host_parts
         | 
| @@ -255,6 +373,13 @@ module Elasticsearch | |
| 255 373 | 
             
                      ::Faraday.default_adapter
         | 
| 256 374 | 
             
                    end
         | 
| 257 375 | 
             
                  end
         | 
| 376 | 
            +
             | 
| 377 | 
            +
                  # Encode credentials for the Authorization Header
         | 
| 378 | 
            +
                  # Credentials is the base64 encoding of id and api_key joined by a colon
         | 
| 379 | 
            +
                  # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
         | 
| 380 | 
            +
                  def __encode(api_key)
         | 
| 381 | 
            +
                    Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':'))
         | 
| 382 | 
            +
                  end
         | 
| 258 383 | 
             
                end
         | 
| 259 384 | 
             
              end
         | 
| 260 385 | 
             
            end
         | 
| @@ -0,0 +1,135 @@ | |
| 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 | 
            +
             | 
| 18 | 
            +
            require 'base64'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            module Elasticsearch
         | 
| 21 | 
            +
              module Transport
         | 
| 22 | 
            +
                # Methods for the Elastic meta header used by Cloud.
         | 
| 23 | 
            +
                # X-Elastic-Client-Meta HTTP header which is used by Elastic Cloud and can be disabled when
         | 
| 24 | 
            +
                # instantiating the Client with the :enable_meta_header parameter set to `false`.
         | 
| 25 | 
            +
                #
         | 
| 26 | 
            +
                module MetaHeader
         | 
| 27 | 
            +
                  def set_meta_header
         | 
| 28 | 
            +
                    return if @arguments[:enable_meta_header] == false
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    service, version = meta_header_service_version
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    meta_headers = {
         | 
| 33 | 
            +
                      service.to_sym => version,
         | 
| 34 | 
            +
                      rb: RUBY_VERSION,
         | 
| 35 | 
            +
                      t: Elasticsearch::Transport::VERSION
         | 
| 36 | 
            +
                    }
         | 
| 37 | 
            +
                    meta_headers.merge!(meta_header_engine) if meta_header_engine
         | 
| 38 | 
            +
                    meta_headers.merge!(meta_header_adapter) if meta_header_adapter
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    add_header({ 'x-elastic-client-meta' => meta_headers.map { |k, v| "#{k}=#{v}" }.join(',') })
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def meta_header_service_version
         | 
| 44 | 
            +
                    if enterprise_search?
         | 
| 45 | 
            +
                      Elastic::ENTERPRISE_SERVICE_VERSION
         | 
| 46 | 
            +
                    elsif elasticsearch?
         | 
| 47 | 
            +
                      Elastic::ELASTICSEARCH_SERVICE_VERSION
         | 
| 48 | 
            +
                    elsif defined?(Elasticsearch::VERSION)
         | 
| 49 | 
            +
                      [:es, client_meta_version(Elasticsearch::VERSION)]
         | 
| 50 | 
            +
                    else
         | 
| 51 | 
            +
                      [:es, client_meta_version(Elasticsearch::Transport::VERSION)]
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  def enterprise_search?
         | 
| 56 | 
            +
                    defined?(Elastic::ENTERPRISE_SERVICE_VERSION) &&
         | 
| 57 | 
            +
                      called_from?('enterprise-search-ruby')
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  def elasticsearch?
         | 
| 61 | 
            +
                    defined?(Elastic::ELASTICSEARCH_SERVICE_VERSION) &&
         | 
| 62 | 
            +
                      called_from?('elasticsearch')
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  def called_from?(service)
         | 
| 66 | 
            +
                    !caller.select { |c| c.match?(service) }.empty?
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  # We return the current version if it's a release, but if it's a pre/alpha/beta release we
         | 
| 70 | 
            +
                  # return <VERSION_NUMBER>p
         | 
| 71 | 
            +
                  #
         | 
| 72 | 
            +
                  def client_meta_version(version)
         | 
| 73 | 
            +
                    regexp = /^([0-9]+\.[0-9]+\.[0-9]+)(\.?[a-z0-9.-]+)?$/
         | 
| 74 | 
            +
                    match = version.match(regexp)
         | 
| 75 | 
            +
                    return "#{match[1]}p" if (match[2])
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    version
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def meta_header_engine
         | 
| 81 | 
            +
                    case RUBY_ENGINE
         | 
| 82 | 
            +
                    when 'ruby'
         | 
| 83 | 
            +
                      {}
         | 
| 84 | 
            +
                    when 'jruby'
         | 
| 85 | 
            +
                      { jv: ENV_JAVA['java.version'], jr: JRUBY_VERSION }
         | 
| 86 | 
            +
                    when 'rbx'
         | 
| 87 | 
            +
                      { rbx: RUBY_VERSION }
         | 
| 88 | 
            +
                    else
         | 
| 89 | 
            +
                      { RUBY_ENGINE.to_sym => RUBY_VERSION }
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  # This function tries to define the version for the Faraday adapter. If it hasn't been loaded
         | 
| 94 | 
            +
                  # by the time we're calling this method, it's going to report the adapter (if we know it) but
         | 
| 95 | 
            +
                  # return 0 as the version. It won't report anything when using a custom adapter we don't
         | 
| 96 | 
            +
                  # identify.
         | 
| 97 | 
            +
                  #
         | 
| 98 | 
            +
                  # Returns a Hash<adapter_alias, version>
         | 
| 99 | 
            +
                  #
         | 
| 100 | 
            +
                  def meta_header_adapter
         | 
| 101 | 
            +
                    if @transport_class == Transport::HTTP::Faraday
         | 
| 102 | 
            +
                      version = '0'
         | 
| 103 | 
            +
                      adapter_version = case @arguments[:adapter]
         | 
| 104 | 
            +
                               when :patron
         | 
| 105 | 
            +
                                 version = Patron::VERSION if defined?(::Patron::VERSION)
         | 
| 106 | 
            +
                                 {pt: version}
         | 
| 107 | 
            +
                               when :net_http
         | 
| 108 | 
            +
                                 version = if defined?(Net::HTTP::VERSION)
         | 
| 109 | 
            +
                                             Net::HTTP::VERSION
         | 
| 110 | 
            +
                                           elsif defined?(Net::HTTP::HTTPVersion)
         | 
| 111 | 
            +
                                             Net::HTTP::HTTPVersion
         | 
| 112 | 
            +
                                           end
         | 
| 113 | 
            +
                                 {nh: version}
         | 
| 114 | 
            +
                               when :typhoeus
         | 
| 115 | 
            +
                                 version = Typhoeus::VERSION if defined?(::Typhoeus::VERSION)
         | 
| 116 | 
            +
                                 {ty: version}
         | 
| 117 | 
            +
                               when :httpclient
         | 
| 118 | 
            +
                                 version = HTTPClient::VERSION if defined?(HTTPClient::VERSION)
         | 
| 119 | 
            +
                                 {hc: version}
         | 
| 120 | 
            +
                               when :net_http_persistent
         | 
| 121 | 
            +
                                 version = Net::HTTP::Persistent::VERSION if defined?(Net::HTTP::Persistent::VERSION)
         | 
| 122 | 
            +
                                 {np: version}
         | 
| 123 | 
            +
                               else
         | 
| 124 | 
            +
                                 {}
         | 
| 125 | 
            +
                               end
         | 
| 126 | 
            +
                      {fd: Faraday::VERSION}.merge(adapter_version)
         | 
| 127 | 
            +
                    elsif defined?(Transport::HTTP::Curb) && @transport_class == Transport::HTTP::Curb
         | 
| 128 | 
            +
                      {cl: Curl::CURB_VERSION}
         | 
| 129 | 
            +
                    elsif defined?(Transport::HTTP::Manticore) && @transport_class == Transport::HTTP::Manticore
         | 
| 130 | 
            +
                      {mc: Manticore::VERSION}
         | 
| 131 | 
            +
                    end
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
              end
         | 
| 135 | 
            +
            end
         | 
| @@ -1,6 +1,19 @@ | |
| 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 | 
             
            module Elasticsearch
         | 
| 6 19 | 
             
              module Transport
         |