httpx 0.24.1 → 0.24.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 588deec0af9ead32480f7cca9ce8c278b344ccdd2e608cc2a6a8db8c6135647f
4
- data.tar.gz: 3b69af49050cd6ba7b0317ddcd2286cbe6a2261add9fd0b9839bb89290e3962a
3
+ metadata.gz: 145a6e293b5ae6bfc1008765a755ab823d490edf7c50bdbf1de01194e3e1537b
4
+ data.tar.gz: 42d235a66fdb050a993b305d3aefed91893d26253cc62864ff2d0d088167ef0a
5
5
  SHA512:
6
- metadata.gz: e630447fb6bc2aabb6efd842fdd322734e78e7859ea03126ab3d45cf4580d91ede945aa4e77700ae6cbe92179cc0a7e96fdc294ccaf729b287c4b4269b9b40b8
7
- data.tar.gz: 138310fead4041c202f32b3e53564023472383f5cc251c59cc88b115c8f2947801da8269518d3dce48ff8b53abe3b1350d92b553a9264be8ab052064a135b605
6
+ metadata.gz: 7b10d4d91debc907d3445526ab864357a1e39cddfbe8b628f104241ed9015ae340e122dd49535be21bda7b20b95ebc047db4c476b7ff412e310d685f835e62c3
7
+ data.tar.gz: 3d82a8bc8bc3d5e6f94c2dde6f330ab52a3a42e0cd95e4b62328e4b6b005aac9946d1903d384f0944112e997ca26801dc342d77b44290dddb8e88ec0523e1338
@@ -0,0 +1,12 @@
1
+ # 0.24.2
2
+
3
+ ## Improvements
4
+
5
+ * besides an array, `:resolver_options` can now receive a hash for `:nameserver`, which **must** be indexed by IP family (`Socket::AF_INET6` or `Socket::AF_INET`); each group of nameservers will be used for emitting DNS queries of that iP family.
6
+ * `:authentication` plugin: Added `#bearer_auth` helper, which receives a token, and sets it as `"Bearer $TOKEN` in the `"authorization"` header.
7
+ * `faraday` adapter: now implements `#build_connection` and `#close`, will now interact with `faraday` native timeouts (`:read`, `:write` and `:connect`).
8
+
9
+
10
+ ## Bugfixes
11
+
12
+ * fixed native resolver bug when queries involving intermediate alias would be kept after the original query and mess with re-queries.
@@ -0,0 +1,12 @@
1
+ # 0.24.3
2
+
3
+ ## Improvements
4
+
5
+ * faraday adapter: reraise httpx timeout errors as faraday errors.
6
+ * faraday adapter: support `:bind` option, which expects a host and port to connect to.
7
+
8
+ ## Bugfixes
9
+
10
+ * faraday adapter: fix `#close` implementation using the wrong ivar.
11
+ * faraday adapter: fix usage of `requestt_timeout` translation of faraday timeouts into httpx timeouts.
12
+ * faraday adapter: `ssl: { verify: false }` was being ignored, and certification verification was still proceeding.
@@ -35,8 +35,55 @@ module Faraday
35
35
  module RequestMixin
36
36
  using ::HTTPX::HashExtensions
37
37
 
38
+ def build_connection(env)
39
+ return @connection if defined?(@connection)
40
+
41
+ @connection = ::HTTPX.plugin(:compression).plugin(:persistent).plugin(ReasonPlugin)
42
+ @connection = @connection.with(@connection_options) unless @connection_options.empty?
43
+ connection_opts = options_from_env(env)
44
+
45
+ if (bind = env.request.bind)
46
+ @bind = TCPSocket.new(bind[:host], bind[:port])
47
+ connection_opts[:io] = @bind
48
+ end
49
+ @connection = @connection.with(connection_opts)
50
+
51
+ if (proxy = env.request.proxy)
52
+ proxy_options = { uri: proxy.uri }
53
+ proxy_options[:username] = proxy.user if proxy.user
54
+ proxy_options[:password] = proxy.password if proxy.password
55
+
56
+ @connection = @connection.plugin(:proxy).with(proxy: proxy_options)
57
+ end
58
+ @connection = @connection.plugin(OnDataPlugin) if env.request.stream_response?
59
+
60
+ @connection
61
+ end
62
+
63
+ def close
64
+ @connection.close if @connection
65
+ @bind.close if @bind
66
+ end
67
+
38
68
  private
39
69
 
70
+ def connect(env, &blk)
71
+ connection(env, &blk)
72
+ rescue ::HTTPX::TLSError => e
73
+ raise SSL_ERROR, e
74
+ rescue Errno::ECONNABORTED,
75
+ Errno::ECONNREFUSED,
76
+ Errno::ECONNRESET,
77
+ Errno::EHOSTUNREACH,
78
+ Errno::EINVAL,
79
+ Errno::ENETUNREACH,
80
+ Errno::EPIPE,
81
+ ::HTTPX::ConnectionError => e
82
+ raise CONNECTION_FAILED_ERROR, e
83
+ rescue ::HTTPX::TimeoutError => e
84
+ raise Faraday::TimeoutError, e
85
+ end
86
+
40
87
  def build_request(env)
41
88
  meth = env[:method]
42
89
 
@@ -48,28 +95,40 @@ module Faraday
48
95
  end
49
96
 
50
97
  def options_from_env(env)
51
- timeout_options = {
52
- connect_timeout: env.request.open_timeout,
53
- operation_timeout: env.request.timeout,
54
- }.compact
98
+ timeout_options = {}
99
+ req_opts = env.request
100
+ if (sec = request_timeout(:read, req_opts))
101
+ timeout_options[:operation_timeout] = sec
102
+ end
103
+
104
+ if (sec = request_timeout(:write, req_opts))
105
+ timeout_options[:operation_timeout] = sec
106
+ end
107
+
108
+ if (sec = request_timeout(:open, req_opts))
109
+ timeout_options[:connect_timeout] = sec
110
+ end
111
+
112
+ ssl_options = {}
113
+
114
+ unless env.ssl.verify.nil?
115
+ ssl_options[:verify_mode] = env.ssl.verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
116
+ end
55
117
 
56
- options = {
57
- ssl: {},
118
+ ssl_options[:ca_file] = env.ssl.ca_file if env.ssl.ca_file
119
+ ssl_options[:ca_path] = env.ssl.ca_path if env.ssl.ca_path
120
+ ssl_options[:cert_store] = env.ssl.cert_store if env.ssl.cert_store
121
+ ssl_options[:cert] = env.ssl.client_cert if env.ssl.client_cert
122
+ ssl_options[:key] = env.ssl.client_key if env.ssl.client_key
123
+ ssl_options[:ssl_version] = env.ssl.version if env.ssl.version
124
+ ssl_options[:verify_depth] = env.ssl.verify_depth if env.ssl.verify_depth
125
+ ssl_options[:min_version] = env.ssl.min_version if env.ssl.min_version
126
+ ssl_options[:max_version] = env.ssl.max_version if env.ssl.max_version
127
+
128
+ {
129
+ ssl: ssl_options,
58
130
  timeout: timeout_options,
59
131
  }
60
-
61
- options[:ssl][:verify_mode] = OpenSSL::SSL::VERIFY_PEER if env.ssl.verify
62
- options[:ssl][:ca_file] = env.ssl.ca_file if env.ssl.ca_file
63
- options[:ssl][:ca_path] = env.ssl.ca_path if env.ssl.ca_path
64
- options[:ssl][:cert_store] = env.ssl.cert_store if env.ssl.cert_store
65
- options[:ssl][:cert] = env.ssl.client_cert if env.ssl.client_cert
66
- options[:ssl][:key] = env.ssl.client_key if env.ssl.client_key
67
- options[:ssl][:ssl_version] = env.ssl.version if env.ssl.version
68
- options[:ssl][:verify_depth] = env.ssl.verify_depth if env.ssl.verify_depth
69
- options[:ssl][:min_version] = env.ssl.min_version if env.ssl.min_version
70
- options[:ssl][:max_version] = env.ssl.max_version if env.ssl.max_version
71
-
72
- options
73
132
  end
74
133
  end
75
134
 
@@ -122,10 +181,6 @@ module Faraday
122
181
  end
123
182
  end
124
183
 
125
- def self.session
126
- @session ||= ::HTTPX.plugin(:compression).plugin(:persistent).plugin(ReasonPlugin)
127
- end
128
-
129
184
  class ParallelManager
130
185
  class ResponseHandler < SimpleDelegator
131
186
  attr_reader :env
@@ -158,8 +213,9 @@ module Faraday
158
213
 
159
214
  include RequestMixin
160
215
 
161
- def initialize
216
+ def initialize(options)
162
217
  @handlers = []
218
+ @connection_options = options
163
219
  end
164
220
 
165
221
  def enqueue(request)
@@ -173,40 +229,54 @@ module Faraday
173
229
 
174
230
  env = @handlers.last.env
175
231
 
176
- session = HTTPX.session.with(options_from_env(env))
177
- session = session.plugin(:proxy).with(proxy: { uri: env.request.proxy }) if env.request.proxy
178
- session = session.plugin(OnDataPlugin) if env.request.stream_response?
232
+ connect(env) do |session|
233
+ requests = @handlers.map { |handler| session.build_request(*build_request(handler.env)) }
179
234
 
180
- requests = @handlers.map { |handler| session.build_request(*build_request(handler.env)) }
235
+ if env.request.stream_response?
236
+ requests.each do |request|
237
+ request.response_on_data = env.request.on_data
238
+ end
239
+ end
181
240
 
182
- if env.request.stream_response?
183
- requests.each do |request|
184
- request.response_on_data = env.request.on_data
241
+ responses = session.request(*requests)
242
+ Array(responses).each_with_index do |response, index|
243
+ handler = @handlers[index]
244
+ handler.on_response.call(response)
245
+ handler.on_complete.call(handler.env)
185
246
  end
186
247
  end
248
+ rescue ::HTTPX::TimeoutError => e
249
+ raise Faraday::TimeoutError, e
250
+ end
251
+
252
+ # from Faraday::Adapter#connection
253
+ def connection(env)
254
+ conn = build_connection(env)
255
+ return conn unless block_given?
256
+
257
+ yield conn
258
+ end
259
+
260
+ private
187
261
 
188
- responses = session.request(*requests)
189
- Array(responses).each_with_index do |response, index|
190
- handler = @handlers[index]
191
- handler.on_response.call(response)
192
- handler.on_complete.call(handler.env)
262
+ # from Faraday::Adapter#request_timeout
263
+ def request_timeout(type, options)
264
+ key = Faraday::Adapter::TIMEOUT_KEYS.fetch(type) do
265
+ msg = "Expected :read, :write, :open. Got #{type.inspect} :("
266
+ raise ArgumentError, msg
193
267
  end
268
+ options[key] || options[:timeout]
194
269
  end
195
270
  end
196
271
 
197
272
  self.supports_parallel = true
198
273
 
199
274
  class << self
200
- def setup_parallel_manager
201
- ParallelManager.new
275
+ def setup_parallel_manager(options = {})
276
+ ParallelManager.new(options)
202
277
  end
203
278
  end
204
279
 
205
- def initialize(app, options = {})
206
- super(app)
207
- @session_options = options
208
- end
209
-
210
280
  def call(env)
211
281
  super
212
282
  if parallel?(env)
@@ -224,38 +294,30 @@ module Faraday
224
294
  return handler
225
295
  end
226
296
 
227
- session = HTTPX.session
228
- session = session.with(@session_options) unless @session_options.empty?
229
- session = session.with(options_from_env(env))
230
- session = session.plugin(:proxy).with(proxy: { uri: env.request.proxy }) if env.request.proxy
231
- session = session.plugin(OnDataPlugin) if env.request.stream_response?
232
-
233
- request = session.build_request(*build_request(env))
234
-
235
- request.response_on_data = env.request.on_data if env.request.stream_response?
236
-
237
- response = session.request(request)
238
- # do not call #raise_for_status for HTTP 4xx or 5xx, as faraday has a middleware for that.
239
- response.raise_for_status unless response.is_a?(::HTTPX::Response)
297
+ response = connect_and_request(env)
240
298
  save_response(env, response.status, response.body.to_s, response.headers, response.reason) do |response_headers|
241
299
  response_headers.merge!(response.headers)
242
300
  end
243
301
  @app.call(env)
244
- rescue ::HTTPX::TLSError => e
245
- raise SSL_ERROR, e
246
- rescue Errno::ECONNABORTED,
247
- Errno::ECONNREFUSED,
248
- Errno::ECONNRESET,
249
- Errno::EHOSTUNREACH,
250
- Errno::EINVAL,
251
- Errno::ENETUNREACH,
252
- Errno::EPIPE,
253
- ::HTTPX::ConnectionError => e
254
- raise CONNECTION_FAILED_ERROR, e
255
302
  end
256
303
 
257
304
  private
258
305
 
306
+ def connect_and_request(env)
307
+ connect(env) do |session|
308
+ request = session.build_request(*build_request(env))
309
+
310
+ request.response_on_data = env.request.on_data if env.request.stream_response?
311
+
312
+ response = session.request(request)
313
+ # do not call #raise_for_status for HTTP 4xx or 5xx, as faraday has a middleware for that.
314
+ response.raise_for_status unless response.is_a?(::HTTPX::Response)
315
+ response
316
+ end
317
+ rescue ::HTTPX::TimeoutError => e
318
+ raise Faraday::TimeoutError, e
319
+ end
320
+
259
321
  def parallel?(env)
260
322
  env[:parallel_manager]
261
323
  end
@@ -13,6 +13,10 @@ module HTTPX
13
13
  def authentication(token)
14
14
  with(headers: { "authorization" => token })
15
15
  end
16
+
17
+ def bearer_auth(token)
18
+ authentication("Bearer #{token}")
19
+ end
16
20
  end
17
21
  end
18
22
  register_plugin :authentication, Authentication
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
+ require_relative "store"
4
5
 
5
6
  module HTTPX::Plugins
6
7
  module ResponseCache
@@ -29,12 +29,15 @@ module HTTPX
29
29
 
30
30
  attr_reader :state
31
31
 
32
- def initialize(_, options)
32
+ def initialize(family, options)
33
33
  super
34
34
  @ns_index = 0
35
35
  @resolver_options = DEFAULTS.merge(@options.resolver_options)
36
36
  @socket_type = @resolver_options.fetch(:socket_type, :udp)
37
- @nameserver = Array(@resolver_options[:nameserver]) if @resolver_options[:nameserver]
37
+ @nameserver = if (nameserver = @resolver_options[:nameserver])
38
+ nameserver = nameserver[family] if nameserver.is_a?(Hash)
39
+ Array(nameserver)
40
+ end
38
41
  @ndots = @resolver_options[:ndots]
39
42
  @search = Array(@resolver_options[:search]).map { |srch| srch.scan(/[^.]+/) }
40
43
  @_timeouts = Array(@resolver_options[:timeouts])
@@ -318,7 +321,7 @@ module HTTPX
318
321
  return
319
322
  end
320
323
  else
321
- @timeouts.delete(name)
324
+ reset_hostname(name, connection: connection)
322
325
  @timeouts.delete(connection.origin.host)
323
326
  @connections.delete(connection)
324
327
  Resolver.cached_lookup_set(connection.origin.host, @family, addresses) if @resolver_options[:cache]
@@ -429,9 +432,8 @@ module HTTPX
429
432
  end
430
433
  end
431
434
 
432
- def reset_hostname(hostname, reset_candidates: true)
435
+ def reset_hostname(hostname, connection: @queries.delete(hostname), reset_candidates: true)
433
436
  @timeouts.delete(hostname)
434
- connection = @queries.delete(hostname)
435
437
  @timeouts.delete(hostname)
436
438
 
437
439
  return unless connection && reset_candidates
data/lib/httpx/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- VERSION = "0.24.1"
4
+ VERSION = "0.24.3"
5
5
  end
@@ -3,6 +3,8 @@ module HTTPX
3
3
  module Authentication
4
4
  module InstanceMethods
5
5
  def authentication: (string token) -> instance
6
+
7
+ def bearer_auth: (string token) -> instance
6
8
  end
7
9
  end
8
10
 
@@ -63,7 +63,7 @@ module HTTPX
63
63
 
64
64
  def handle_error: (NativeResolveError | StandardError) -> void
65
65
 
66
- def reset_hostname: (String hostname, ?reset_candidates: bool) -> void
66
+ def reset_hostname: (String hostname, ?connection: Connection, ?reset_candidates: bool) -> void
67
67
  end
68
68
  end
69
69
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.1
4
+ version: 0.24.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-27 00:00:00.000000000 Z
11
+ date: 2023-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2-next
@@ -101,6 +101,8 @@ extra_rdoc_files:
101
101
  - doc/release_notes/0_23_4.md
102
102
  - doc/release_notes/0_24_0.md
103
103
  - doc/release_notes/0_24_1.md
104
+ - doc/release_notes/0_24_2.md
105
+ - doc/release_notes/0_24_3.md
104
106
  - doc/release_notes/0_2_0.md
105
107
  - doc/release_notes/0_2_1.md
106
108
  - doc/release_notes/0_3_0.md
@@ -194,6 +196,8 @@ files:
194
196
  - doc/release_notes/0_23_4.md
195
197
  - doc/release_notes/0_24_0.md
196
198
  - doc/release_notes/0_24_1.md
199
+ - doc/release_notes/0_24_2.md
200
+ - doc/release_notes/0_24_3.md
197
201
  - doc/release_notes/0_2_0.md
198
202
  - doc/release_notes/0_2_1.md
199
203
  - doc/release_notes/0_3_0.md