httpx 1.5.1 → 1.6.0
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/doc/release_notes/1_6_0.md +50 -0
- data/lib/httpx/adapters/datadog.rb +23 -13
- data/lib/httpx/adapters/faraday.rb +14 -9
- data/lib/httpx/adapters/webmock.rb +1 -1
- data/lib/httpx/callbacks.rb +1 -1
- data/lib/httpx/connection/http1.rb +5 -6
- data/lib/httpx/connection/http2.rb +30 -12
- data/lib/httpx/connection.rb +17 -24
- data/lib/httpx/errors.rb +3 -1
- data/lib/httpx/io/ssl.rb +1 -4
- data/lib/httpx/io/tcp.rb +25 -16
- data/lib/httpx/io/unix.rb +4 -3
- data/lib/httpx/loggable.rb +4 -1
- data/lib/httpx/options.rb +252 -158
- data/lib/httpx/plugins/aws_sdk_authentication.rb +2 -0
- data/lib/httpx/plugins/aws_sigv4.rb +2 -0
- data/lib/httpx/plugins/callbacks.rb +13 -1
- data/lib/httpx/plugins/circuit_breaker.rb +2 -0
- data/lib/httpx/plugins/content_digest.rb +2 -0
- data/lib/httpx/plugins/cookies.rb +2 -2
- data/lib/httpx/plugins/digest_auth.rb +2 -0
- data/lib/httpx/plugins/expect.rb +2 -0
- data/lib/httpx/plugins/fiber_concurrency.rb +195 -0
- data/lib/httpx/plugins/follow_redirects.rb +2 -0
- data/lib/httpx/plugins/grpc.rb +2 -0
- data/lib/httpx/plugins/h2c.rb +26 -16
- data/lib/httpx/plugins/internal_telemetry.rb +0 -49
- data/lib/httpx/plugins/ntlm_auth.rb +2 -0
- data/lib/httpx/plugins/oauth.rb +2 -0
- data/lib/httpx/plugins/persistent.rb +27 -18
- data/lib/httpx/plugins/proxy/socks4.rb +1 -1
- data/lib/httpx/plugins/proxy/socks5.rb +1 -1
- data/lib/httpx/plugins/proxy/ssh.rb +2 -0
- data/lib/httpx/plugins/proxy.rb +61 -20
- data/lib/httpx/plugins/response_cache/file_store.rb +2 -2
- data/lib/httpx/plugins/response_cache.rb +2 -0
- data/lib/httpx/plugins/retries.rb +2 -0
- data/lib/httpx/plugins/ssrf_filter.rb +2 -2
- data/lib/httpx/plugins/stream_bidi.rb +3 -3
- data/lib/httpx/plugins/upgrade/h2.rb +11 -1
- data/lib/httpx/plugins/upgrade.rb +8 -0
- data/lib/httpx/pool.rb +15 -10
- data/lib/httpx/request/body.rb +8 -3
- data/lib/httpx/request.rb +22 -11
- data/lib/httpx/resolver/entry.rb +30 -0
- data/lib/httpx/resolver/https.rb +3 -1
- data/lib/httpx/resolver/multi.rb +5 -2
- data/lib/httpx/resolver/native.rb +15 -6
- data/lib/httpx/resolver/resolver.rb +3 -5
- data/lib/httpx/resolver/system.rb +1 -1
- data/lib/httpx/resolver.rb +34 -21
- data/lib/httpx/response/body.rb +1 -1
- data/lib/httpx/response/buffer.rb +13 -18
- data/lib/httpx/selector.rb +92 -34
- data/lib/httpx/session.rb +89 -30
- data/lib/httpx/session_extensions.rb +3 -2
- data/lib/httpx/transcoder/form.rb +1 -13
- data/lib/httpx/transcoder/multipart/mime_type_detector.rb +1 -1
- data/lib/httpx/transcoder/multipart.rb +14 -0
- data/lib/httpx/transcoder/utils/deflater.rb +1 -1
- data/lib/httpx/version.rb +1 -1
- data/sig/callbacks.rbs +1 -1
- data/sig/chainable.rbs +1 -0
- data/sig/connection/http1.rbs +2 -0
- data/sig/connection/http2.rbs +4 -0
- data/sig/connection.rbs +6 -6
- data/sig/errors.rbs +3 -1
- data/sig/io/ssl.rbs +1 -1
- data/sig/io/tcp.rbs +13 -7
- data/sig/io/udp.rbs +7 -2
- data/sig/io/unix.rbs +0 -1
- data/sig/io.rbs +0 -3
- data/sig/options.rbs +63 -10
- data/sig/plugins/fiber_concurrency.rbs +51 -0
- data/sig/plugins/h2c.rbs +5 -1
- data/sig/plugins/persistent.rbs +1 -1
- data/sig/plugins/proxy/socks4.rbs +1 -1
- data/sig/plugins/proxy/socks5.rbs +1 -1
- data/sig/plugins/proxy.rbs +5 -2
- data/sig/plugins/ssrf_filter.rbs +1 -1
- data/sig/plugins/stream_bidi.rbs +2 -2
- data/sig/request.rbs +4 -1
- data/sig/resolver/entry.rbs +13 -0
- data/sig/resolver/native.rbs +1 -0
- data/sig/resolver/resolver.rbs +2 -3
- data/sig/resolver/system.rbs +2 -2
- data/sig/resolver.rbs +10 -11
- data/sig/response.rbs +2 -2
- data/sig/selector.rbs +18 -10
- data/sig/session.rbs +4 -0
- data/sig/transcoder/form.rbs +3 -3
- data/sig/transcoder/multipart.rbs +9 -3
- metadata +9 -3
data/lib/httpx/selector.rb
CHANGED
@@ -3,6 +3,21 @@
|
|
3
3
|
require "io/wait"
|
4
4
|
|
5
5
|
module HTTPX
|
6
|
+
#
|
7
|
+
# Implements the selector loop, where it registers and monitors "Selectable" objects.
|
8
|
+
#
|
9
|
+
# A Selectable object is an object which can calculate the **interests** (<tt>:r</tt>, <tt>:w</tt> or <tt>:rw</tt>,
|
10
|
+
# respectively "read", "write" or "read-write") it wants to monitor for, and returns (via <tt>to_io</tt> method) an
|
11
|
+
# IO object which can be passed to functions such as IO.select . More exhaustively, a Selectable **must** implement
|
12
|
+
# the following methods:
|
13
|
+
#
|
14
|
+
# state :: returns the state as a Symbol, must return <tt>:closed</tt> when disposed of resources.
|
15
|
+
# to_io :: returns the IO object.
|
16
|
+
# call :: gets called when the IO is ready.
|
17
|
+
# interests :: returns the current interests to monitor for, as described above.
|
18
|
+
# timeout :: returns nil or an integer, representing how long to wait for interests.
|
19
|
+
# handle_socket_timeout(Numeric) :: called when waiting for interest times out.
|
20
|
+
#
|
6
21
|
class Selector
|
7
22
|
extend Forwardable
|
8
23
|
|
@@ -123,38 +138,75 @@ module HTTPX
|
|
123
138
|
private
|
124
139
|
|
125
140
|
def select(interval, &block)
|
141
|
+
has_no_selectables = @selectables.empty?
|
126
142
|
# do not cause an infinite loop here.
|
127
143
|
#
|
128
144
|
# this may happen if timeout calculation actually triggered an error which causes
|
129
145
|
# the connections to be reaped (such as the total timeout error) before #select
|
130
146
|
# gets called.
|
131
|
-
return if interval.nil? &&
|
147
|
+
return if interval.nil? && has_no_selectables
|
132
148
|
|
133
|
-
|
134
|
-
|
135
|
-
select_many(interval, &block)
|
136
|
-
end
|
137
|
-
|
138
|
-
def select_many(interval, &block)
|
149
|
+
# @type var r: (selectable | Array[selectable])?
|
150
|
+
# @type var w: (selectable | Array[selectable])?
|
139
151
|
r, w = nil
|
140
152
|
|
141
|
-
# first, we group IOs based on interest type. On call to #interests however,
|
142
|
-
# things might already happen, and new IOs might be registered, so we might
|
143
|
-
# have to start all over again. We do this until we group all selectables
|
144
153
|
@selectables.delete_if do |io|
|
145
154
|
interests = io.interests
|
146
155
|
|
156
|
+
is_closed = io.state == :closed
|
157
|
+
|
158
|
+
next(is_closed) if is_closed
|
159
|
+
|
147
160
|
io.log(level: 2) { "[#{io.state}] registering for select (#{interests})#{" for #{interval} seconds" unless interval.nil?}" }
|
148
161
|
|
149
|
-
|
150
|
-
|
162
|
+
if READABLE.include?(interests)
|
163
|
+
r = r.nil? ? io : (Array(r) << io)
|
164
|
+
end
|
165
|
+
|
166
|
+
if WRITABLE.include?(interests)
|
167
|
+
w = w.nil? ? io : (Array(w) << io)
|
168
|
+
end
|
151
169
|
|
152
|
-
|
170
|
+
is_closed
|
153
171
|
end
|
154
172
|
|
155
|
-
|
173
|
+
case r
|
174
|
+
when Array
|
175
|
+
w = Array(w) unless w.nil?
|
176
|
+
|
177
|
+
select_many(r, w, interval, &block)
|
178
|
+
when nil
|
179
|
+
case w
|
180
|
+
when Array
|
181
|
+
select_many(r, w, interval, &block)
|
182
|
+
when nil
|
183
|
+
return unless interval && has_no_selectables
|
184
|
+
|
185
|
+
# no selectables
|
186
|
+
# TODO: replace with sleep?
|
187
|
+
select_many(r, w, interval, &block)
|
188
|
+
else
|
189
|
+
select_one(w, :w, interval, &block)
|
190
|
+
end
|
156
191
|
|
157
|
-
|
192
|
+
else
|
193
|
+
case w
|
194
|
+
when Array
|
195
|
+
select_many(Array(r), w, interval, &block)
|
196
|
+
when nil
|
197
|
+
select_one(r, :r, interval, &block)
|
198
|
+
else
|
199
|
+
if r == w
|
200
|
+
select_one(r, :rw, interval, &block)
|
201
|
+
else
|
202
|
+
select_many(Array(r), Array(w), interval, &block)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def select_many(r, w, interval, &block)
|
209
|
+
readers, writers = ::IO.select(r, w, nil, interval)
|
158
210
|
|
159
211
|
if readers.nil? && writers.nil? && interval
|
160
212
|
[*r, *w].each { |io| io.handle_socket_timeout(interval) }
|
@@ -175,32 +227,20 @@ module HTTPX
|
|
175
227
|
end
|
176
228
|
end
|
177
229
|
|
178
|
-
def select_one(interval)
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
io.log(level: 2) { "[#{io.state}] registering for select (#{interests})#{" for #{interval} seconds" unless interval.nil?}" }
|
186
|
-
|
187
|
-
result = case interests
|
188
|
-
when :r then io.to_io.wait_readable(interval)
|
189
|
-
when :w then io.to_io.wait_writable(interval)
|
190
|
-
when :rw then io.to_io.wait(interval, :read_write)
|
191
|
-
when nil then return
|
192
|
-
end
|
230
|
+
def select_one(io, interests, interval)
|
231
|
+
result =
|
232
|
+
case interests
|
233
|
+
when :r then io.to_io.wait_readable(interval)
|
234
|
+
when :w then io.to_io.wait_writable(interval)
|
235
|
+
when :rw then rw_wait(io, interval)
|
236
|
+
end
|
193
237
|
|
194
238
|
unless result || interval.nil?
|
195
239
|
io.handle_socket_timeout(interval) unless @is_timer_interval
|
196
240
|
return
|
197
241
|
end
|
198
|
-
# raise TimeoutError.new(interval, "timed out while waiting on select")
|
199
242
|
|
200
243
|
yield io
|
201
|
-
# rescue IOError, SystemCallError
|
202
|
-
# @selectables.reject!(&:closed?)
|
203
|
-
# raise unless @selectables.empty?
|
204
244
|
end
|
205
245
|
|
206
246
|
def next_timeout
|
@@ -220,5 +260,23 @@ module HTTPX
|
|
220
260
|
|
221
261
|
connection_interval
|
222
262
|
end
|
263
|
+
|
264
|
+
if RUBY_ENGINE == "jruby"
|
265
|
+
def rw_wait(io, interval)
|
266
|
+
io.to_io.wait(interval, :read_write)
|
267
|
+
end
|
268
|
+
elsif IO.const_defined?(:READABLE)
|
269
|
+
def rw_wait(io, interval)
|
270
|
+
io.to_io.wait(IO::READABLE | IO::WRITABLE, interval)
|
271
|
+
end
|
272
|
+
else
|
273
|
+
def rw_wait(io, interval)
|
274
|
+
if interval
|
275
|
+
io.to_io.wait(interval, :read_write)
|
276
|
+
else
|
277
|
+
io.to_io.wait(:read_write)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
223
281
|
end
|
224
282
|
end
|
data/lib/httpx/session.rb
CHANGED
@@ -71,12 +71,8 @@ module HTTPX
|
|
71
71
|
|
72
72
|
select_connection(connection, selector)
|
73
73
|
end
|
74
|
-
|
75
|
-
|
76
|
-
selector.terminate
|
77
|
-
ensure
|
78
|
-
@closing = false
|
79
|
-
end
|
74
|
+
|
75
|
+
selector_close(selector)
|
80
76
|
end
|
81
77
|
|
82
78
|
# performs one, or multple requests; it accepts:
|
@@ -136,6 +132,9 @@ module HTTPX
|
|
136
132
|
alias_method :select_resolver, :select_connection
|
137
133
|
|
138
134
|
def deselect_connection(connection, selector, cloned = false)
|
135
|
+
connection.log(level: 2) do
|
136
|
+
"deregistering connection##{connection.object_id}(#{connection.state}) from selector##{selector.object_id}"
|
137
|
+
end
|
139
138
|
selector.deregister(connection)
|
140
139
|
|
141
140
|
# when connections coalesce
|
@@ -145,14 +144,19 @@ module HTTPX
|
|
145
144
|
|
146
145
|
return if @closing && connection.state == :closed
|
147
146
|
|
147
|
+
connection.log(level: 2) { "check-in connection##{connection.object_id}(#{connection.state}) in pool##{@pool.object_id}" }
|
148
148
|
@pool.checkin_connection(connection)
|
149
149
|
end
|
150
150
|
|
151
151
|
def deselect_resolver(resolver, selector)
|
152
|
+
resolver.log(level: 2) do
|
153
|
+
"deregistering resolver##{resolver.object_id}(#{resolver.state}) from selector##{selector.object_id}"
|
154
|
+
end
|
152
155
|
selector.deregister(resolver)
|
153
156
|
|
154
157
|
return if @closing && resolver.closed?
|
155
158
|
|
159
|
+
resolver.log(level: 2) { "check-in resolver##{resolver.object_id}(#{resolver.state}) in pool##{@pool.object_id}" }
|
156
160
|
@pool.checkin_resolver(resolver)
|
157
161
|
end
|
158
162
|
|
@@ -194,7 +198,12 @@ module HTTPX
|
|
194
198
|
end
|
195
199
|
when :closing, :closed
|
196
200
|
connection.idling
|
197
|
-
|
201
|
+
if connection.addresses?
|
202
|
+
select_connection(connection, selector)
|
203
|
+
else
|
204
|
+
# if addresses expired, resolve again
|
205
|
+
resolve_connection(connection, selector)
|
206
|
+
end
|
198
207
|
else
|
199
208
|
pin_connection(connection, selector)
|
200
209
|
end
|
@@ -204,10 +213,23 @@ module HTTPX
|
|
204
213
|
|
205
214
|
private
|
206
215
|
|
216
|
+
def selector_close(selector)
|
217
|
+
begin
|
218
|
+
@closing = true
|
219
|
+
selector.terminate
|
220
|
+
ensure
|
221
|
+
@closing = false
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# tries deactivating connections in the +selector+, deregistering the ones that have been deactivated.
|
207
226
|
def deactivate(selector)
|
208
|
-
selector.each_connection do |
|
209
|
-
|
210
|
-
|
227
|
+
selector.each_connection.select do |c|
|
228
|
+
c.deactivate
|
229
|
+
|
230
|
+
c.state == :inactive
|
231
|
+
end.each do |c| # rubocop:disable Style/MultilineBlockChain
|
232
|
+
deselect_connection(c, selector)
|
211
233
|
end
|
212
234
|
end
|
213
235
|
|
@@ -221,7 +243,11 @@ module HTTPX
|
|
221
243
|
def fetch_response(request, _selector, _options)
|
222
244
|
response = request.response
|
223
245
|
|
224
|
-
|
246
|
+
return unless response && response.finished?
|
247
|
+
|
248
|
+
log(level: 2) { "response fetched" }
|
249
|
+
|
250
|
+
response
|
225
251
|
end
|
226
252
|
|
227
253
|
# sends the +request+ to the corresponding HTTPX::Connection
|
@@ -303,8 +329,7 @@ module HTTPX
|
|
303
329
|
|
304
330
|
# returns the array of HTTPX::Response objects corresponding to the array of HTTPX::Request +requests+.
|
305
331
|
def receive_requests(requests, selector)
|
306
|
-
|
307
|
-
responses = []
|
332
|
+
responses = [] # : Array[response]
|
308
333
|
|
309
334
|
# guarantee ordered responses
|
310
335
|
loop do
|
@@ -313,7 +338,7 @@ module HTTPX
|
|
313
338
|
return responses unless request
|
314
339
|
|
315
340
|
catch(:coalesced) { selector.next_tick } until (response = fetch_response(request, selector, request.options))
|
316
|
-
request.
|
341
|
+
request.complete!(response)
|
317
342
|
|
318
343
|
responses << response
|
319
344
|
requests.shift
|
@@ -326,18 +351,36 @@ module HTTPX
|
|
326
351
|
# handshake error, and the error responses have already been emitted, but there was no
|
327
352
|
# opportunity to traverse the requests, hence we're returning only a fraction of the errors
|
328
353
|
# we were supposed to. This effectively fetches the existing responses and return them.
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
354
|
+
exit_from_loop = true
|
355
|
+
|
356
|
+
requests_to_remove = [] # : Array[Request]
|
357
|
+
|
358
|
+
requests.each do |req|
|
359
|
+
response = fetch_response(req, selector, request.options)
|
360
|
+
|
361
|
+
if exit_from_loop && response
|
362
|
+
req.complete!(response)
|
363
|
+
responses << response
|
364
|
+
requests_to_remove << req
|
365
|
+
else
|
366
|
+
# fetch_response may resend requests. when that happens, we need to go back to the initial
|
367
|
+
# loop and process the selector. we still do a pass-through on the remainder of requests, so
|
368
|
+
# that every request that need to be resent, is resent.
|
369
|
+
exit_from_loop = false
|
370
|
+
|
371
|
+
raise Error, "something went wrong, responses not found and requests not resent" if selector.empty?
|
372
|
+
end
|
333
373
|
end
|
334
|
-
|
374
|
+
|
375
|
+
break if exit_from_loop
|
376
|
+
|
377
|
+
requests -= requests_to_remove
|
335
378
|
end
|
336
379
|
responses
|
337
380
|
end
|
338
381
|
|
339
382
|
def resolve_connection(connection, selector)
|
340
|
-
if connection.addresses || connection.open?
|
383
|
+
if connection.addresses? || connection.open?
|
341
384
|
#
|
342
385
|
# there are two cases in which we want to activate initialization of
|
343
386
|
# connection immediately:
|
@@ -380,14 +423,16 @@ module HTTPX
|
|
380
423
|
end
|
381
424
|
|
382
425
|
def find_resolver_for(connection, selector)
|
383
|
-
resolver = selector.find_resolver(connection.options)
|
384
|
-
|
385
|
-
|
386
|
-
resolver = @pool.checkout_resolver(connection.options)
|
387
|
-
resolver.current_session = self
|
388
|
-
resolver.current_selector = selector
|
426
|
+
if (resolver = selector.find_resolver(connection.options))
|
427
|
+
resolver.log(level: 2) { "found resolver##{connection.object_id}(#{connection.state}) in selector##{selector.object_id}" }
|
428
|
+
return resolver
|
389
429
|
end
|
390
430
|
|
431
|
+
resolver = @pool.checkout_resolver(connection.options)
|
432
|
+
resolver.log(level: 2) { "found resolver##{connection.object_id}(#{connection.state}) in pool##{@pool.object_id}" }
|
433
|
+
resolver.current_session = self
|
434
|
+
resolver.current_selector = selector
|
435
|
+
|
391
436
|
resolver
|
392
437
|
end
|
393
438
|
|
@@ -397,7 +442,10 @@ module HTTPX
|
|
397
442
|
unless conn1.coalescable?(conn2)
|
398
443
|
conn2.log(level: 2) { "not coalescing with conn##{conn1.object_id}[#{conn1.origin}])" }
|
399
444
|
select_connection(conn2, selector)
|
400
|
-
|
445
|
+
if from_pool
|
446
|
+
conn1.log(level: 2) { "check-in connection##{conn1.object_id}(#{conn1.state}) in pool##{@pool.object_id}" }
|
447
|
+
@pool.checkin_connection(conn1)
|
448
|
+
end
|
401
449
|
return false
|
402
450
|
end
|
403
451
|
|
@@ -422,13 +470,18 @@ module HTTPX
|
|
422
470
|
|
423
471
|
def selector_store
|
424
472
|
th_current = Thread.current
|
425
|
-
|
473
|
+
|
474
|
+
thread_selector_store(th_current) || begin
|
426
475
|
{}.compare_by_identity.tap do |store|
|
427
476
|
th_current.thread_variable_set(:httpx_persistent_selector_store, store)
|
428
477
|
end
|
429
478
|
end
|
430
479
|
end
|
431
480
|
|
481
|
+
def thread_selector_store(th)
|
482
|
+
th.thread_variable_get(:httpx_persistent_selector_store)
|
483
|
+
end
|
484
|
+
|
432
485
|
@default_options = Options.new
|
433
486
|
@default_options.freeze
|
434
487
|
@plugins = []
|
@@ -452,6 +505,8 @@ module HTTPX
|
|
452
505
|
label = pl
|
453
506
|
# raise Error, "Cannot add a plugin to a frozen config" if frozen?
|
454
507
|
pl = Plugins.load_plugin(pl) if pl.is_a?(Symbol)
|
508
|
+
raise ArgumentError, "Invalid plugin type: #{pl.class.inspect}" unless pl.is_a?(Module)
|
509
|
+
|
455
510
|
if !@plugins.include?(pl)
|
456
511
|
@plugins << pl
|
457
512
|
pl.load_dependencies(self, &block) if pl.respond_to?(:load_dependencies)
|
@@ -463,9 +518,13 @@ module HTTPX
|
|
463
518
|
|
464
519
|
opts = @default_options
|
465
520
|
opts.extend_with_plugin_classes(pl)
|
466
|
-
if defined?(pl::OptionsMethods)
|
467
521
|
|
468
|
-
|
522
|
+
if defined?(pl::OptionsMethods)
|
523
|
+
# when a class gets dup'ed, the #initialize_dup callbacks isn't triggered.
|
524
|
+
# moreover, and because #method_added does not get triggered on mixin include,
|
525
|
+
# the callback is also forcefully manually called here.
|
526
|
+
opts.options_class.instance_variable_set(:@options_names, opts.options_class.options_names.dup)
|
527
|
+
(pl::OptionsMethods.instance_methods + pl::OptionsMethods.private_instance_methods - Object.instance_methods).each do |meth|
|
469
528
|
opts.options_class.method_added(meth)
|
470
529
|
end
|
471
530
|
@default_options = opts.options_class.new(opts)
|
@@ -11,8 +11,9 @@ module HTTPX
|
|
11
11
|
options = proxy_session.class.default_options.to_hash
|
12
12
|
original_verbosity = $VERBOSE
|
13
13
|
$VERBOSE = nil
|
14
|
-
|
15
|
-
|
14
|
+
new_options_class = proxy_session.class.default_options.options_class.dup
|
15
|
+
const_set(:Options, new_options_class)
|
16
|
+
options[:options_class] = Class.new(new_options_class).freeze
|
16
17
|
options.freeze
|
17
18
|
Options.send(:const_set, :DEFAULT_OPTIONS, options)
|
18
19
|
Session.instance_variable_set(:@default_options, Options.new(options))
|
@@ -48,11 +48,7 @@ module HTTPX
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def encode(form)
|
51
|
-
|
52
|
-
Multipart::Encoder.new(form)
|
53
|
-
else
|
54
|
-
Encoder.new(form)
|
55
|
-
end
|
51
|
+
Encoder.new(form)
|
56
52
|
end
|
57
53
|
|
58
54
|
def decode(response)
|
@@ -67,14 +63,6 @@ module HTTPX
|
|
67
63
|
raise Error, "invalid form mime type (#{content_type})"
|
68
64
|
end
|
69
65
|
end
|
70
|
-
|
71
|
-
def multipart?(data)
|
72
|
-
data.any? do |_, v|
|
73
|
-
Multipart::MULTIPART_VALUE_COND.call(v) ||
|
74
|
-
(v.respond_to?(:to_ary) && v.to_ary.any?(&Multipart::MULTIPART_VALUE_COND)) ||
|
75
|
-
(v.respond_to?(:to_hash) && v.to_hash.any? { |_, e| Multipart::MULTIPART_VALUE_COND.call(e) })
|
76
|
-
end
|
77
|
-
end
|
78
66
|
end
|
79
67
|
end
|
80
68
|
end
|
@@ -13,5 +13,19 @@ module HTTPX::Transcoder
|
|
13
13
|
value.key?(:body) &&
|
14
14
|
(value.key?(:filename) || value.key?(:content_type)))
|
15
15
|
end
|
16
|
+
|
17
|
+
module_function
|
18
|
+
|
19
|
+
def multipart?(form_data)
|
20
|
+
form_data.any? do |_, v|
|
21
|
+
Multipart::MULTIPART_VALUE_COND.call(v) ||
|
22
|
+
(v.respond_to?(:to_ary) && v.to_ary.any?(&Multipart::MULTIPART_VALUE_COND)) ||
|
23
|
+
(v.respond_to?(:to_hash) && v.to_hash.any? { |_, e| Multipart::MULTIPART_VALUE_COND.call(e) })
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def encode(form_data)
|
28
|
+
Encoder.new(form_data)
|
29
|
+
end
|
16
30
|
end
|
17
31
|
end
|
data/lib/httpx/version.rb
CHANGED
data/sig/callbacks.rbs
CHANGED
@@ -8,7 +8,7 @@ module HTTPX
|
|
8
8
|
def once: (Symbol) { (*untyped) -> void } -> ^(*untyped) -> void
|
9
9
|
def emit: (Symbol, *untyped) -> void
|
10
10
|
|
11
|
-
def callbacks_for?: (Symbol) ->
|
11
|
+
def callbacks_for?: (Symbol) -> boolish
|
12
12
|
def callbacks: () -> Hash[Symbol, Array[_Callable]]
|
13
13
|
| (Symbol) -> Array[_Callable]
|
14
14
|
end
|
data/sig/chainable.rbs
CHANGED
@@ -24,6 +24,7 @@ module HTTPX
|
|
24
24
|
| (:upgrade, ?options) -> Plugins::sessionUpgrade
|
25
25
|
| (:h2c, ?options) -> Plugins::sessionUpgrade
|
26
26
|
| (:h2, ?options) -> Plugins::sessionUpgrade
|
27
|
+
| (:fiber_concurrency, ?options) -> Plugins::sessionFiberConcurrency
|
27
28
|
| (:persistent, ?options) -> Plugins::sessionPersistent
|
28
29
|
| (:proxy, ?options) -> (Plugins::sessionProxy & Plugins::httpProxy)
|
29
30
|
| (:push_promise, ?options) -> Plugins::sessionPushPromise
|
data/sig/connection/http1.rbs
CHANGED
data/sig/connection/http2.rbs
CHANGED
@@ -37,6 +37,8 @@ module HTTPX
|
|
37
37
|
|
38
38
|
def ping: () -> void
|
39
39
|
|
40
|
+
def waiting_for_ping?: () -> bool
|
41
|
+
|
40
42
|
alias reset init_connection
|
41
43
|
|
42
44
|
def timeout: () -> Numeric?
|
@@ -97,6 +99,8 @@ module HTTPX
|
|
97
99
|
|
98
100
|
def on_pong: (string ping) -> void
|
99
101
|
|
102
|
+
def teardown: (?Request? request) -> void
|
103
|
+
|
100
104
|
class Error < ::HTTPX::Error
|
101
105
|
def initialize: (Integer id, Symbol | StandardError error) -> void
|
102
106
|
end
|
data/sig/connection.rbs
CHANGED
@@ -50,17 +50,17 @@ module HTTPX
|
|
50
50
|
@main_sibling: bool
|
51
51
|
|
52
52
|
|
53
|
-
def addresses: () -> Array[
|
53
|
+
def addresses: () -> Array[Resolver::Entry]?
|
54
54
|
|
55
55
|
def peer: () -> URI::Generic
|
56
56
|
|
57
|
-
def addresses=: (Array[
|
57
|
+
def addresses=: (Array[Resolver::Entry] addresses) -> void
|
58
58
|
|
59
59
|
def send: (Request request) -> void
|
60
60
|
|
61
|
-
def
|
61
|
+
def addresses?: () -> boolish
|
62
62
|
|
63
|
-
def
|
63
|
+
def match?: (URI::Generic uri, Options options) -> bool
|
64
64
|
|
65
65
|
def mergeable?: (Connection connection) -> bool
|
66
66
|
|
@@ -82,7 +82,7 @@ module HTTPX
|
|
82
82
|
|
83
83
|
def interests: () -> io_interests?
|
84
84
|
|
85
|
-
def to_io: () ->
|
85
|
+
def to_io: () -> IO
|
86
86
|
|
87
87
|
def call: () -> void
|
88
88
|
|
@@ -140,7 +140,7 @@ module HTTPX
|
|
140
140
|
|
141
141
|
def build_altsvc_connection: (URI::Generic alt_origin, String origin, Hash[String, String] alt_params) -> void
|
142
142
|
|
143
|
-
def build_socket: (?Array[
|
143
|
+
def build_socket: (?Array[Resolver::Entry]? addrs) -> (TCP | SSL | UNIX)
|
144
144
|
|
145
145
|
def on_error: (HTTPX::TimeoutError | Error | StandardError error, ?Request? request) -> void
|
146
146
|
|
data/sig/errors.rbs
CHANGED
@@ -51,13 +51,15 @@ module HTTPX
|
|
51
51
|
class HTTPError < Error
|
52
52
|
attr_reader response: Response
|
53
53
|
|
54
|
+
def status: () -> Integer
|
55
|
+
|
54
56
|
private
|
55
57
|
|
56
58
|
def initialize: (Response response) -> void
|
57
59
|
end
|
58
60
|
|
59
61
|
class NativeResolveError < ResolveError
|
60
|
-
|
62
|
+
attr_accessor connection: Connection?
|
61
63
|
attr_reader host: String
|
62
64
|
|
63
65
|
private
|
data/sig/io/ssl.rbs
CHANGED
@@ -12,7 +12,7 @@ module HTTPX
|
|
12
12
|
attr_writer ssl_session: OpenSSL::SSL::Session?
|
13
13
|
|
14
14
|
# TODO: lift when https://github.com/ruby/rbs/issues/1497 fixed
|
15
|
-
# def initialize: (URI::Generic origin, Array[
|
15
|
+
# def initialize: (URI::Generic origin, Array[Resolver::Entry]? addresses, options options) ?{ (self) -> void } -> void
|
16
16
|
|
17
17
|
def session_new_cb: { (OpenSSL::SSL::Session sess) -> void } -> void
|
18
18
|
def can_verify_peer?: () -> bool
|
data/sig/io/tcp.rbs
CHANGED
@@ -2,11 +2,11 @@ module HTTPX
|
|
2
2
|
class TCP
|
3
3
|
include Loggable
|
4
4
|
|
5
|
-
attr_reader ip:
|
5
|
+
attr_reader ip: Resolver::Entry?
|
6
6
|
|
7
7
|
attr_reader port: Integer
|
8
8
|
|
9
|
-
attr_reader addresses: Array[
|
9
|
+
attr_reader addresses: Array[Resolver::Entry]
|
10
10
|
|
11
11
|
attr_reader state: Symbol
|
12
12
|
|
@@ -14,18 +14,26 @@ module HTTPX
|
|
14
14
|
|
15
15
|
alias host ip
|
16
16
|
|
17
|
+
@io: Socket
|
18
|
+
|
17
19
|
@hostname: String
|
18
20
|
|
19
21
|
@options: Options
|
20
22
|
|
21
23
|
@fallback_protocol: String
|
22
24
|
|
25
|
+
@keep_open: bool
|
26
|
+
|
27
|
+
@ip_index: Integer
|
28
|
+
|
23
29
|
# TODO: lift when https://github.com/ruby/rbs/issues/1497 fixed
|
24
|
-
def initialize: (URI::Generic origin, Array[
|
30
|
+
def initialize: (URI::Generic origin, Array[Resolver::Entry]? addresses, Options options) ?{ (instance) -> void } -> void
|
25
31
|
|
26
|
-
def add_addresses: (Array[
|
32
|
+
def add_addresses: (Array[Resolver::Entry] addrs) -> void
|
27
33
|
|
28
|
-
def
|
34
|
+
def addresses?: () -> bool
|
35
|
+
|
36
|
+
def to_io: () -> IO
|
29
37
|
|
30
38
|
def protocol: () -> String
|
31
39
|
|
@@ -46,8 +54,6 @@ module HTTPX
|
|
46
54
|
|
47
55
|
def connected?: () -> bool
|
48
56
|
|
49
|
-
def expired?: () -> boolish
|
50
|
-
|
51
57
|
def closed?: () -> bool
|
52
58
|
|
53
59
|
# :nocov:
|