elasticsearch-transport 7.1.0 → 7.13.3

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +13 -9
  3. data/{LICENSE.txt → LICENSE} +0 -0
  4. data/README.md +175 -76
  5. data/Rakefile +1 -1
  6. data/elasticsearch-transport.gemspec +42 -60
  7. data/lib/elasticsearch/transport/client.rb +154 -57
  8. data/lib/elasticsearch/transport/meta_header.rb +135 -0
  9. data/lib/elasticsearch/transport/redacted.rb +1 -1
  10. data/lib/elasticsearch/transport/transport/base.rb +93 -18
  11. data/lib/elasticsearch/transport/transport/connections/collection.rb +3 -6
  12. data/lib/elasticsearch/transport/transport/connections/connection.rb +8 -6
  13. data/lib/elasticsearch/transport/transport/connections/selector.rb +18 -6
  14. data/lib/elasticsearch/transport/transport/errors.rb +1 -1
  15. data/lib/elasticsearch/transport/transport/http/curb.rb +26 -9
  16. data/lib/elasticsearch/transport/transport/http/faraday.rb +27 -5
  17. data/lib/elasticsearch/transport/transport/http/manticore.rb +25 -10
  18. data/lib/elasticsearch/transport/transport/loggable.rb +1 -1
  19. data/lib/elasticsearch/transport/transport/response.rb +1 -2
  20. data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +1 -1
  21. data/lib/elasticsearch/transport/transport/sniffer.rb +20 -12
  22. data/lib/elasticsearch/transport/version.rb +2 -2
  23. data/lib/elasticsearch/transport.rb +1 -1
  24. data/lib/elasticsearch-transport.rb +1 -1
  25. data/spec/elasticsearch/connections/collection_spec.rb +266 -0
  26. data/spec/elasticsearch/connections/selector_spec.rb +174 -0
  27. data/spec/elasticsearch/transport/base_spec.rb +197 -13
  28. data/spec/elasticsearch/transport/client_spec.rb +945 -118
  29. data/spec/elasticsearch/transport/meta_header_spec.rb +265 -0
  30. data/spec/elasticsearch/transport/sniffer_spec.rb +1 -14
  31. data/spec/spec_helper.rb +25 -1
  32. data/test/integration/transport_test.rb +15 -2
  33. data/test/profile/client_benchmark_test.rb +1 -1
  34. data/test/test_helper.rb +1 -1
  35. data/test/unit/connection_test.rb +8 -3
  36. data/test/unit/response_test.rb +2 -2
  37. data/test/unit/serializer_test.rb +1 -1
  38. data/test/unit/transport_base_test.rb +2 -2
  39. data/test/unit/transport_curb_test.rb +2 -2
  40. data/test/unit/transport_faraday_test.rb +3 -3
  41. data/test/unit/transport_manticore_test.rb +30 -14
  42. metadata +87 -60
  43. data/test/unit/connection_collection_test.rb +0 -147
  44. data/test/unit/connection_selector_test.rb +0 -81
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -19,7 +19,6 @@ module Elasticsearch
19
19
  module Transport
20
20
  module Transport
21
21
  module Connections
22
-
23
22
  # Wraps the connection information and logic.
24
23
  #
25
24
  # The Connection instance wraps the host information (hostname, port, attributes, etc),
@@ -54,12 +53,14 @@ module Elasticsearch
54
53
  #
55
54
  # @return [String]
56
55
  #
57
- def full_url(path, params={})
56
+ def full_url(path, params = {})
58
57
  url = "#{host[:protocol]}://"
59
58
  url += "#{CGI.escape(host[:user])}:#{CGI.escape(host[:password])}@" if host[:user]
60
59
  url += "#{host[:host]}:#{host[:port]}"
61
60
  url += "#{host[:path]}" if host[:path]
62
- url += "/#{full_path(path, params)}"
61
+ full_path = full_path(path, params)
62
+ url += '/' unless full_path.match?(/^\//)
63
+ url += full_path
63
64
  end
64
65
 
65
66
  # Returns the complete endpoint path with serialized parameters.
@@ -135,14 +136,15 @@ module Elasticsearch
135
136
  }
136
137
  end
137
138
 
138
- # Equality operator based on connection protocol, host and port
139
+ # Equality operator based on connection protocol, host, port and attributes
139
140
  #
140
141
  # @return [Boolean]
141
142
  #
142
143
  def ==(other)
143
144
  self.host[:protocol] == other.host[:protocol] && \
144
145
  self.host[:host] == other.host[:host] && \
145
- self.host[:port].to_i == other.host[:port].to_i
146
+ self.host[:port].to_i == other.host[:port].to_i && \
147
+ self.host[:attributes] == other.host[:attributes]
146
148
  end
147
149
 
148
150
  # @return [String]
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -61,18 +61,30 @@ module Elasticsearch
61
61
  class RoundRobin
62
62
  include Base
63
63
 
64
+ # @option arguments [Connections::Collection] :connections Collection with connections.
65
+ #
66
+ def initialize(arguments = {})
67
+ super
68
+ @mutex = Mutex.new
69
+ @current = nil
70
+ end
71
+
64
72
  # Returns the next connection from the collection, rotating them in round-robin fashion.
65
73
  #
66
74
  # @return [Connections::Connection]
67
75
  #
68
76
  def select(options={})
69
- # On Ruby 1.9, Array#rotate could be used instead
70
- @current = !defined?(@current) || @current.nil? ? 0 : @current+1
71
- @current = 0 if @current >= connections.size
72
- connections[@current]
77
+ @mutex.synchronize do
78
+ conns = connections
79
+ if @current && (@current < conns.size-1)
80
+ @current += 1
81
+ else
82
+ @current = 0
83
+ end
84
+ conns[@current]
85
+ end
73
86
  end
74
87
  end
75
-
76
88
  end
77
89
  end
78
90
  end
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -32,7 +32,7 @@ module Elasticsearch
32
32
  # @return [Response]
33
33
  # @see Transport::Base#perform_request
34
34
  #
35
- def perform_request(method, path, params={}, body=nil, headers=nil)
35
+ def perform_request(method, path, params={}, body=nil, headers=nil, opts={})
36
36
  super do |connection, url|
37
37
  connection.connection.url = connection.full_url(path, params)
38
38
 
@@ -43,7 +43,15 @@ module Elasticsearch
43
43
  connection.connection.set :nobody, false
44
44
 
45
45
  connection.connection.put_data = __convert_to_json(body) if body
46
- connection.connection.headers = headers if headers
46
+
47
+ if headers
48
+ if connection.connection.headers
49
+ connection.connection.headers.merge!(headers)
50
+ else
51
+ connection.connection.headers = headers
52
+ end
53
+ end
54
+
47
55
  else raise ArgumentError, "Unsupported HTTP method: #{method}"
48
56
  end
49
57
 
@@ -53,7 +61,7 @@ module Elasticsearch
53
61
  response_headers['content-type'] = 'application/json' if connection.connection.header_str =~ /\/json/
54
62
 
55
63
  Response.new connection.connection.response_code,
56
- connection.connection.body_str,
64
+ decompress_response(connection.connection.body_str),
57
65
  response_headers
58
66
  end
59
67
  end
@@ -65,10 +73,7 @@ module Elasticsearch
65
73
  def __build_connection(host, options={}, block=nil)
66
74
  client = ::Curl::Easy.new
67
75
 
68
- headers = options[:headers] || {}
69
- headers.update('User-Agent' => "Curb #{Curl::CURB_VERSION}")
70
-
71
- client.headers = headers
76
+ apply_headers(client, options)
72
77
  client.url = __full_url(host)
73
78
 
74
79
  if host[:user]
@@ -96,8 +101,20 @@ module Elasticsearch
96
101
  ::Curl::Err::TimeoutError
97
102
  ]
98
103
  end
99
- end
100
104
 
105
+ private
106
+
107
+ def user_agent_header(client)
108
+ @user_agent ||= begin
109
+ meta = ["RUBY_VERSION: #{RUBY_VERSION}"]
110
+ if RbConfig::CONFIG && RbConfig::CONFIG['host_os']
111
+ meta << "#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase} #{RbConfig::CONFIG['target_cpu']}"
112
+ end
113
+ meta << "Curb #{Curl::CURB_VERSION}"
114
+ "elasticsearch-ruby/#{VERSION} (#{meta.join('; ')})"
115
+ end
116
+ end
117
+ end
101
118
  end
102
119
  end
103
120
  end
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -33,16 +33,24 @@ module Elasticsearch
33
33
  # @return [Response]
34
34
  # @see Transport::Base#perform_request
35
35
  #
36
- def perform_request(method, path, params={}, body=nil, headers=nil)
36
+ def perform_request(method, path, params = {}, body = nil, headers = nil, opts = {})
37
37
  super do |connection, url|
38
- headers = headers || connection.connection.headers
38
+ headers = if connection.connection.headers
39
+ if !headers.nil?
40
+ connection.connection.headers.merge(headers)
41
+ else
42
+ connection.connection.headers
43
+ end
44
+ else
45
+ headers
46
+ end
39
47
 
40
48
  response = connection.connection.run_request(method.downcase.to_sym,
41
49
  url,
42
50
  ( body ? __convert_to_json(body) : nil ),
43
51
  headers)
44
52
 
45
- Response.new response.status, response.body, response.headers
53
+ Response.new response.status, decompress_response(response.body), response.headers
46
54
  end
47
55
  end
48
56
 
@@ -52,6 +60,7 @@ module Elasticsearch
52
60
  #
53
61
  def __build_connection(host, options={}, block=nil)
54
62
  client = ::Faraday.new(__full_url(host), options, &block)
63
+ apply_headers(client, options)
55
64
  Connections::Connection.new :host => host, :connection => client
56
65
  end
57
66
 
@@ -60,7 +69,20 @@ module Elasticsearch
60
69
  # @return [Array]
61
70
  #
62
71
  def host_unreachable_exceptions
63
- [::Faraday::Error::ConnectionFailed, ::Faraday::Error::TimeoutError]
72
+ [::Faraday::ConnectionFailed, ::Faraday::TimeoutError]
73
+ end
74
+
75
+ private
76
+
77
+ def user_agent_header(client)
78
+ @user_agent ||= begin
79
+ meta = ["RUBY_VERSION: #{RUBY_VERSION}"]
80
+ if RbConfig::CONFIG && RbConfig::CONFIG['host_os']
81
+ meta << "#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase} #{RbConfig::CONFIG['target_cpu']}"
82
+ end
83
+ meta << "#{client.headers[USER_AGENT_STR]}"
84
+ "elasticsearch-ruby/#{VERSION} (#{meta.join('; ')})"
85
+ end
64
86
  end
65
87
  end
66
88
  end
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -80,7 +80,7 @@ module Elasticsearch
80
80
  # @return [Response]
81
81
  # @see Transport::Base#perform_request
82
82
  #
83
- def perform_request(method, path, params={}, body=nil, headers=nil)
83
+ def perform_request(method, path, params={}, body=nil, headers=nil, opts={})
84
84
  super do |connection, url|
85
85
  params[:body] = __convert_to_json(body) if body
86
86
  params[:headers] = headers if headers
@@ -110,14 +110,8 @@ module Elasticsearch
110
110
  #
111
111
  def __build_connections
112
112
  @request_options = {}
113
-
114
- if options[:transport_options] && options[:transport_options][:headers]
115
- @request_options[:headers] = options[:transport_options][:headers]
116
- end
117
-
118
- if options.key?(:headers)
119
- @request_options[:headers] = options[:headers]
120
- end
113
+ apply_headers(@request_options, options[:transport_options])
114
+ apply_headers(@request_options, options)
121
115
 
122
116
  Connections::Collection.new \
123
117
  :connections => hosts.map { |host|
@@ -157,6 +151,27 @@ module Elasticsearch
157
151
  ::Manticore::ResolutionFailure
158
152
  ]
159
153
  end
154
+
155
+ private
156
+
157
+ def apply_headers(request_options, options)
158
+ headers = (options && options[:headers]) || {}
159
+ headers[CONTENT_TYPE_STR] = find_value(headers, CONTENT_TYPE_REGEX) || DEFAULT_CONTENT_TYPE
160
+ headers[USER_AGENT_STR] = find_value(headers, USER_AGENT_REGEX) || user_agent_header
161
+ headers[ACCEPT_ENCODING] = GZIP if use_compression?
162
+ request_options.merge!(headers: headers)
163
+ end
164
+
165
+ def user_agent_header
166
+ @user_agent ||= begin
167
+ meta = ["RUBY_VERSION: #{JRUBY_VERSION}"]
168
+ if RbConfig::CONFIG && RbConfig::CONFIG['host_os']
169
+ meta << "#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase} #{RbConfig::CONFIG['target_cpu']}"
170
+ end
171
+ meta << "Manticore #{::Manticore::VERSION}"
172
+ "elasticsearch-ruby/#{VERSION} (#{meta.join('; ')})"
173
+ end
174
+ end
160
175
  end
161
176
  end
162
177
  end
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -18,7 +18,6 @@
18
18
  module Elasticsearch
19
19
  module Transport
20
20
  module Transport
21
-
22
21
  # Wraps the response from Elasticsearch.
23
22
  #
24
23
  class Response
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -45,20 +45,21 @@ module Elasticsearch
45
45
  #
46
46
  def hosts
47
47
  Timeout::timeout(timeout, SnifferTimeoutError) do
48
- nodes = transport.perform_request('GET', '_nodes/http').body
48
+ nodes = perform_sniff_request.body
49
49
 
50
50
  hosts = nodes['nodes'].map do |id, info|
51
- if info[PROTOCOL]
52
- host, port = parse_publish_address(info[PROTOCOL]['publish_address'])
51
+ next unless info[PROTOCOL]
52
+ host, port = parse_publish_address(info[PROTOCOL]['publish_address'])
53
53
 
54
- { :id => id,
55
- :name => info['name'],
56
- :version => info['version'],
57
- :host => host,
58
- :port => port,
59
- :roles => info['roles'],
60
- :attributes => info['attributes'] }
61
- end
54
+ {
55
+ id: id,
56
+ name: info['name'],
57
+ version: info['version'],
58
+ host: host,
59
+ port: port,
60
+ roles: info['roles'],
61
+ attributes: info['attributes']
62
+ }
62
63
  end.compact
63
64
 
64
65
  hosts.shuffle! if transport.options[:randomize_hosts]
@@ -68,6 +69,13 @@ module Elasticsearch
68
69
 
69
70
  private
70
71
 
72
+ def perform_sniff_request
73
+ transport.perform_request(
74
+ 'GET', '_nodes/http', {}, nil, nil,
75
+ reload_on_failure: false
76
+ )
77
+ end
78
+
71
79
  def parse_publish_address(publish_address)
72
80
  # publish_address is in the format hostname/ip:port
73
81
  if publish_address =~ /\//
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -17,6 +17,6 @@
17
17
 
18
18
  module Elasticsearch
19
19
  module Transport
20
- VERSION = "7.1.0"
20
+ VERSION = '7.13.3'.freeze
21
21
  end
22
22
  end
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an