httpx 0.24.1 → 0.24.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.
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