httpx 0.24.0 → 0.24.2

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: 159ab63d2464f90d5b73651241f85443c6b79d5d4e0e542cbb93a8e876fd9c97
4
- data.tar.gz: 43c759345b7c52114bea8066ce7e27dd1b026a85bbdf624d1d81f12ce3314248
3
+ metadata.gz: 63f31bb23a4d1676f6d537df456a52e4ee5c4f24e39239072d698abf37cf48fd
4
+ data.tar.gz: b21ec1aeac1a3fdb52be5cccc3e9781bbc8f5e63f81c04a08eb60b89dba00c1b
5
5
  SHA512:
6
- metadata.gz: 4139bbc4d97e28c7c12dcaa9c3a1b71490c9b870cb60d432fb07c946af6b9346f71c8b7554abd30f584fe67b790c8095fa658571769c6a1f527b451604327354
7
- data.tar.gz: 07b636c4eaf69fe3e60c10f4f86a0f8a58e9b1b431d27a9bf7a8b431fba2bdec8f1d4175b5b25de4487d02e90c38b00eaa5b789aacd17b5d3ced34790da55948
6
+ metadata.gz: f0554a088f8ee971e2ccb6534f4d6ef2e43c95c04e6b3930dbeded34485664f340e8c1109a10608c4706098ad43726f2547905eea641b5a45d148ae1f7829e55
7
+ data.tar.gz: 92800524ec31ec676ba7e90a0f51a7d0ea8f6e752253c2b31c0805b807fc2f5fcdbb491f74ceb674e72dd691980cca968a945ec81bd2f9f7ff6eb25b5f9e0a2a
@@ -0,0 +1,12 @@
1
+ # 0.24.1
2
+
3
+ ## Improvements
4
+
5
+ * datadog adapter: support `:service_name` configuration option.
6
+ * datadog adapter: set `:distributed_tracing` to `true` by default.
7
+ * `:proxy` plugin: when the proxy uri uses an unsupported scheme (i.e.: "scp://125.24.2.1"), a more user friendly error is raised (instead of the previous broken stacktrace).
8
+
9
+ ## Bugfixes
10
+
11
+ * datadog adapter: fix tracing enable call, which was wrongly calling `super`.
12
+ + `:proxy` plugin: fix for bug which was turning off plugins overriding `HTTPX::Connection#send` (such as the datadog adapter).
@@ -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.
@@ -160,7 +160,7 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
160
160
 
161
161
  module RequestMethods
162
162
  def __datadog_enable_trace!
163
- return super if @__datadog_enable_trace
163
+ return if @__datadog_enable_trace
164
164
 
165
165
  RequestTracer.new(self).call
166
166
  @__datadog_enable_trace = true
@@ -203,6 +203,27 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
203
203
  o.lazy
204
204
  end
205
205
 
206
+ if defined?(TRACING_MODULE::Contrib::SpanAttributeSchema)
207
+ option :service_name do |o|
208
+ o.default do
209
+ TRACING_MODULE::Contrib::SpanAttributeSchema.fetch_service_name(
210
+ "DD_TRACE_HTTPX_SERVICE_NAME",
211
+ "httpx"
212
+ )
213
+ end
214
+ o.lazy
215
+ end
216
+ else
217
+ option :service_name do |o|
218
+ o.default do
219
+ ENV.fetch("DD_TRACE_HTTPX_SERVICE_NAME", "httpx")
220
+ end
221
+ o.lazy
222
+ end
223
+ end
224
+
225
+ option :distributed_tracing, default: true
226
+
206
227
  option :error_handler, default: DEFAULT_ERROR_HANDLER
207
228
  end
208
229
  end
@@ -35,8 +35,46 @@ 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 = @connection.with(options_from_env(env))
44
+
45
+ if (proxy = env.request.proxy)
46
+ proxy_options = { uri: proxy.uri }
47
+ proxy_options[:username] = proxy.user if proxy.user
48
+ proxy_options[:password] = proxy.password if proxy.password
49
+
50
+ @connection = @connection.plugin(:proxy).with(proxy: proxy_options)
51
+ end
52
+ @connection = @connection.plugin(OnDataPlugin) if env.request.stream_response?
53
+
54
+ @connection
55
+ end
56
+
57
+ def close
58
+ @session.close
59
+ end
60
+
38
61
  private
39
62
 
63
+ def connect(env, &blk)
64
+ connection(env, &blk)
65
+ rescue ::HTTPX::TLSError => e
66
+ raise SSL_ERROR, e
67
+ rescue Errno::ECONNABORTED,
68
+ Errno::ECONNREFUSED,
69
+ Errno::ECONNRESET,
70
+ Errno::EHOSTUNREACH,
71
+ Errno::EINVAL,
72
+ Errno::ENETUNREACH,
73
+ Errno::EPIPE,
74
+ ::HTTPX::ConnectionError => e
75
+ raise CONNECTION_FAILED_ERROR, e
76
+ end
77
+
40
78
  def build_request(env)
41
79
  meth = env[:method]
42
80
 
@@ -48,28 +86,36 @@ module Faraday
48
86
  end
49
87
 
50
88
  def options_from_env(env)
51
- timeout_options = {
52
- connect_timeout: env.request.open_timeout,
53
- operation_timeout: env.request.timeout,
54
- }.compact
89
+ timeout_options = {}
90
+ if (sec = request_timeout(:read, env))
91
+ timeout_options[:operation_timeout] = sec
92
+ end
55
93
 
56
- options = {
57
- ssl: {},
94
+ if (sec = request_timeout(:write, env))
95
+ timeout_options[:operation_timeout] = sec
96
+ end
97
+
98
+ if (sec = request_timeout(:open, env))
99
+ timeout_options[:connect_timeout] = sec
100
+ end
101
+
102
+ ssl_options = {}
103
+
104
+ ssl_options[:verify_mode] = OpenSSL::SSL::VERIFY_PEER if env.ssl.verify
105
+ ssl_options[:ca_file] = env.ssl.ca_file if env.ssl.ca_file
106
+ ssl_options[:ca_path] = env.ssl.ca_path if env.ssl.ca_path
107
+ ssl_options[:cert_store] = env.ssl.cert_store if env.ssl.cert_store
108
+ ssl_options[:cert] = env.ssl.client_cert if env.ssl.client_cert
109
+ ssl_options[:key] = env.ssl.client_key if env.ssl.client_key
110
+ ssl_options[:ssl_version] = env.ssl.version if env.ssl.version
111
+ ssl_options[:verify_depth] = env.ssl.verify_depth if env.ssl.verify_depth
112
+ ssl_options[:min_version] = env.ssl.min_version if env.ssl.min_version
113
+ ssl_options[:max_version] = env.ssl.max_version if env.ssl.max_version
114
+
115
+ {
116
+ ssl: ssl_options,
58
117
  timeout: timeout_options,
59
118
  }
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
119
  end
74
120
  end
75
121
 
@@ -122,10 +168,6 @@ module Faraday
122
168
  end
123
169
  end
124
170
 
125
- def self.session
126
- @session ||= ::HTTPX.plugin(:compression).plugin(:persistent).plugin(ReasonPlugin)
127
- end
128
-
129
171
  class ParallelManager
130
172
  class ResponseHandler < SimpleDelegator
131
173
  attr_reader :env
@@ -158,8 +200,9 @@ module Faraday
158
200
 
159
201
  include RequestMixin
160
202
 
161
- def initialize
203
+ def initialize(options)
162
204
  @handlers = []
205
+ @connection_options = options
163
206
  end
164
207
 
165
208
  def enqueue(request)
@@ -173,40 +216,52 @@ module Faraday
173
216
 
174
217
  env = @handlers.last.env
175
218
 
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?
219
+ connect(env) do |session|
220
+ requests = @handlers.map { |handler| session.build_request(*build_request(handler.env)) }
179
221
 
180
- requests = @handlers.map { |handler| session.build_request(*build_request(handler.env)) }
222
+ if env.request.stream_response?
223
+ requests.each do |request|
224
+ request.response_on_data = env.request.on_data
225
+ end
226
+ end
181
227
 
182
- if env.request.stream_response?
183
- requests.each do |request|
184
- request.response_on_data = env.request.on_data
228
+ responses = session.request(*requests)
229
+ Array(responses).each_with_index do |response, index|
230
+ handler = @handlers[index]
231
+ handler.on_response.call(response)
232
+ handler.on_complete.call(handler.env)
185
233
  end
186
234
  end
235
+ end
187
236
 
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)
237
+ # from Faraday::Adapter#connection
238
+ def connection(env)
239
+ conn = build_connection(env)
240
+ return conn unless block_given?
241
+
242
+ yield conn
243
+ end
244
+
245
+ private
246
+
247
+ # from Faraday::Adapter#request_timeout
248
+ def request_timeout(type, options)
249
+ key = Faraday::Adapter::TIMEOUT_KEYS.fetch(type) do
250
+ msg = "Expected :read, :write, :open. Got #{type.inspect} :("
251
+ raise ArgumentError, msg
193
252
  end
253
+ options[key] || options[:timeout]
194
254
  end
195
255
  end
196
256
 
197
257
  self.supports_parallel = true
198
258
 
199
259
  class << self
200
- def setup_parallel_manager
201
- ParallelManager.new
260
+ def setup_parallel_manager(options = {})
261
+ ParallelManager.new(options)
202
262
  end
203
263
  end
204
264
 
205
- def initialize(app, options = {})
206
- super(app)
207
- @session_options = options
208
- end
209
-
210
265
  def call(env)
211
266
  super
212
267
  if parallel?(env)
@@ -224,38 +279,28 @@ module Faraday
224
279
  return handler
225
280
  end
226
281
 
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)
282
+ response = connect_and_request(env)
240
283
  save_response(env, response.status, response.body.to_s, response.headers, response.reason) do |response_headers|
241
284
  response_headers.merge!(response.headers)
242
285
  end
243
286
  @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
287
  end
256
288
 
257
289
  private
258
290
 
291
+ def connect_and_request(env)
292
+ connect(env) do |session|
293
+ request = session.build_request(*build_request(env))
294
+
295
+ request.response_on_data = env.request.on_data if env.request.stream_response?
296
+
297
+ response = session.request(request)
298
+ # do not call #raise_for_status for HTTP 4xx or 5xx, as faraday has a middleware for that.
299
+ response.raise_for_status unless response.is_a?(::HTTPX::Response)
300
+ response
301
+ end
302
+ end
303
+
259
304
  def parallel?(env)
260
305
  env[:parallel_manager]
261
306
  end
@@ -63,7 +63,7 @@ module HTTPX
63
63
  # Normalizes a _domain_ using the Punycode algorithm as necessary.
64
64
  # The result will be a downcased, ASCII-only string.
65
65
  def normalize(domain)
66
- domain = domain.ascii_only? ? domain : domain.chomp(DOT).unicode_normalize(:nfc)
66
+ domain = domain.chomp(DOT).unicode_normalize(:nfc) unless domain.ascii_only?
67
67
  Punycode.encode_hostname(domain).downcase
68
68
  end
69
69
  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
@@ -6,6 +6,12 @@ module HTTPX
6
6
  module Plugins
7
7
  module Proxy
8
8
  module HTTP
9
+ class << self
10
+ def extra_options(options)
11
+ options.merge(supported_proxy_protocols: options.supported_proxy_protocols + %w[http])
12
+ end
13
+ end
14
+
9
15
  module InstanceMethods
10
16
  def with_proxy_basic_auth(opts)
11
17
  with(proxy: opts.merge(scheme: "basic"))
@@ -16,6 +16,12 @@ module HTTPX
16
16
 
17
17
  Error = Socks4Error
18
18
 
19
+ class << self
20
+ def extra_options(options)
21
+ options.merge(supported_proxy_protocols: options.supported_proxy_protocols + PROTOCOLS)
22
+ end
23
+ end
24
+
19
25
  module ConnectionMethods
20
26
  def interests
21
27
  if @state == :connecting
@@ -18,8 +18,14 @@ module HTTPX
18
18
 
19
19
  Error = Socks5Error
20
20
 
21
- def self.load_dependencies(*)
22
- require_relative "../authentication/socks5"
21
+ class << self
22
+ def load_dependencies(*)
23
+ require_relative "../authentication/socks5"
24
+ end
25
+
26
+ def extra_options(options)
27
+ options.merge(supported_proxy_protocols: options.supported_proxy_protocols + %w[socks5])
28
+ end
23
29
  end
24
30
 
25
31
  module ConnectionMethods
@@ -25,6 +25,10 @@ module HTTPX
25
25
  klass.plugin(:"proxy/socks5")
26
26
  end
27
27
 
28
+ def extra_options(options)
29
+ options.merge(supported_proxy_protocols: [])
30
+ end
31
+
28
32
  if URI::Generic.methods.include?(:use_proxy?)
29
33
  def use_proxy?(*args)
30
34
  URI::Generic.use_proxy?(*args)
@@ -118,6 +122,12 @@ module HTTPX
118
122
  def option_proxy(value)
119
123
  value.is_a?(Parameters) ? value : Hash[value]
120
124
  end
125
+
126
+ def option_supported_proxy_protocols(value)
127
+ raise TypeError, ":supported_proxy_protocols must be an Array" unless value.is_a?(Array)
128
+
129
+ value.map(&:to_s)
130
+ end
121
131
  end
122
132
 
123
133
  module InstanceMethods
@@ -142,8 +152,12 @@ module HTTPX
142
152
  next_proxy = @_proxy_uris.first
143
153
  raise Error, "Failed to connect to proxy" unless next_proxy
144
154
 
155
+ next_proxy = URI(next_proxy)
156
+
157
+ raise Error,
158
+ "#{next_proxy.scheme}: unsupported proxy protocol" unless options.supported_proxy_protocols.include?(next_proxy.scheme)
159
+
145
160
  if proxy.key?(:no_proxy)
146
- next_proxy = URI(next_proxy)
147
161
 
148
162
  no_proxy = proxy[:no_proxy]
149
163
  no_proxy = no_proxy.join(",") if no_proxy.is_a?(Array)
@@ -253,10 +267,11 @@ module HTTPX
253
267
  end
254
268
 
255
269
  def send(request)
256
- return super unless @options.proxy
257
- return super unless connecting?
270
+ return super unless (
271
+ @options.proxy && @state != :idle && connecting?
272
+ )
258
273
 
259
- @pending << request
274
+ (@proxy_pending ||= []) << request
260
275
  end
261
276
 
262
277
  def connecting?
@@ -294,6 +309,12 @@ module HTTPX
294
309
  when :idle
295
310
  transition(:connecting)
296
311
  when :connected
312
+ if @proxy_pending
313
+ while (req = @proxy_pendind.shift)
314
+ send(req)
315
+ end
316
+ end
317
+
297
318
  transition(:open)
298
319
  end
299
320
  end
@@ -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
@@ -9,10 +9,13 @@ module HTTPX
9
9
  # redefine the default options static var, which needs to
10
10
  # refresh options_class
11
11
  options = proxy_session.class.default_options.to_hash
12
- options.freeze
13
12
  original_verbosity = $VERBOSE
14
13
  $VERBOSE = nil
14
+ const_set(:Options, proxy_session.class.default_options.options_class)
15
+ options[:options_class] = Class.new(options[:options_class])
16
+ options.freeze
15
17
  Options.send(:const_set, :DEFAULT_OPTIONS, options)
18
+ Session.instance_variable_set(:@default_options, Options.new(options))
16
19
  $VERBOSE = original_verbosity
17
20
  end
18
21
 
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.0"
4
+ VERSION = "0.24.2"
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.0
4
+ version: 0.24.2
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-15 00:00:00.000000000 Z
11
+ date: 2023-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2-next
@@ -100,6 +100,8 @@ extra_rdoc_files:
100
100
  - doc/release_notes/0_23_3.md
101
101
  - doc/release_notes/0_23_4.md
102
102
  - doc/release_notes/0_24_0.md
103
+ - doc/release_notes/0_24_1.md
104
+ - doc/release_notes/0_24_2.md
103
105
  - doc/release_notes/0_2_0.md
104
106
  - doc/release_notes/0_2_1.md
105
107
  - doc/release_notes/0_3_0.md
@@ -192,6 +194,8 @@ files:
192
194
  - doc/release_notes/0_23_3.md
193
195
  - doc/release_notes/0_23_4.md
194
196
  - doc/release_notes/0_24_0.md
197
+ - doc/release_notes/0_24_1.md
198
+ - doc/release_notes/0_24_2.md
195
199
  - doc/release_notes/0_2_0.md
196
200
  - doc/release_notes/0_2_1.md
197
201
  - doc/release_notes/0_3_0.md
@@ -392,7 +396,7 @@ metadata:
392
396
  changelog_uri: https://os85.gitlab.io/httpx/#release-notes
393
397
  documentation_uri: https://os85.gitlab.io/httpx/rdoc/
394
398
  source_code_uri: https://gitlab.com/os85/httpx
395
- homepage_uri: https://os85.gitlab.io/httpx/
399
+ homepage_uri: https://honeyryderchuck.gitlab.io/httpx/
396
400
  rubygems_mfa_required: 'true'
397
401
  post_install_message:
398
402
  rdoc_options: []
@@ -409,7 +413,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
409
413
  - !ruby/object:Gem::Version
410
414
  version: '0'
411
415
  requirements: []
412
- rubygems_version: 3.4.6
416
+ rubygems_version: 3.4.10
413
417
  signing_key:
414
418
  specification_version: 4
415
419
  summary: HTTPX, to the future, and beyond