httpx 0.15.4 → 0.18.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/0_16_0.md +93 -0
- data/doc/release_notes/0_16_1.md +5 -0
- data/doc/release_notes/0_17_0.md +49 -0
- data/doc/release_notes/0_18_0.md +69 -0
- data/lib/httpx/adapters/datadog.rb +1 -1
- data/lib/httpx/adapters/faraday.rb +8 -14
- data/lib/httpx/adapters/webmock.rb +9 -3
- data/lib/httpx/altsvc.rb +2 -2
- data/lib/httpx/buffer.rb +1 -1
- data/lib/httpx/callbacks.rb +1 -1
- data/lib/httpx/chainable.rb +18 -11
- data/lib/httpx/connection/http1.rb +21 -13
- data/lib/httpx/connection/http2.rb +20 -25
- data/lib/httpx/connection.rb +73 -77
- data/lib/httpx/domain_name.rb +1 -1
- data/lib/httpx/errors.rb +11 -11
- data/lib/httpx/extensions.rb +50 -4
- data/lib/httpx/headers.rb +1 -1
- data/lib/httpx/io/ssl.rb +3 -3
- data/lib/httpx/io/tls.rb +8 -8
- data/lib/httpx/loggable.rb +5 -5
- data/lib/httpx/options.rb +108 -81
- data/lib/httpx/parser/http1.rb +11 -7
- data/lib/httpx/plugins/aws_sdk_authentication.rb +42 -18
- data/lib/httpx/plugins/aws_sigv4.rb +19 -20
- data/lib/httpx/plugins/compression.rb +17 -14
- data/lib/httpx/plugins/cookies/cookie.rb +4 -2
- data/lib/httpx/plugins/cookies/jar.rb +21 -2
- data/lib/httpx/plugins/cookies.rb +20 -7
- data/lib/httpx/plugins/digest_authentication.rb +19 -15
- data/lib/httpx/plugins/expect.rb +26 -18
- data/lib/httpx/plugins/follow_redirects.rb +9 -9
- data/lib/httpx/plugins/grpc/call.rb +4 -1
- data/lib/httpx/plugins/grpc/message.rb +2 -2
- data/lib/httpx/plugins/grpc.rb +72 -46
- data/lib/httpx/plugins/h2c.rb +7 -3
- data/lib/httpx/plugins/internal_telemetry.rb +8 -8
- data/lib/httpx/plugins/multipart/decoder.rb +187 -0
- data/lib/httpx/plugins/multipart/mime_type_detector.rb +3 -3
- data/lib/httpx/plugins/multipart/part.rb +2 -2
- data/lib/httpx/plugins/multipart.rb +16 -2
- data/lib/httpx/plugins/ntlm_authentication.rb +12 -10
- data/lib/httpx/plugins/proxy/socks4.rb +2 -1
- data/lib/httpx/plugins/proxy/socks5.rb +2 -1
- data/lib/httpx/plugins/proxy/ssh.rb +20 -13
- data/lib/httpx/plugins/proxy.rb +10 -10
- data/lib/httpx/plugins/response_cache/store.rb +55 -0
- data/lib/httpx/plugins/response_cache.rb +88 -0
- data/lib/httpx/plugins/retries.rb +46 -23
- data/lib/httpx/plugins/stream.rb +3 -4
- data/lib/httpx/plugins/upgrade.rb +7 -6
- data/lib/httpx/pool.rb +39 -13
- data/lib/httpx/registry.rb +2 -2
- data/lib/httpx/request.rb +16 -25
- data/lib/httpx/resolver/https.rb +4 -8
- data/lib/httpx/resolver/native.rb +19 -5
- data/lib/httpx/resolver/resolver_mixin.rb +2 -1
- data/lib/httpx/resolver/system.rb +2 -0
- data/lib/httpx/resolver.rb +2 -2
- data/lib/httpx/response.rb +91 -48
- data/lib/httpx/selector.rb +11 -24
- data/lib/httpx/session.rb +41 -23
- data/lib/httpx/session2.rb +23 -0
- data/lib/httpx/timers.rb +84 -0
- data/lib/httpx/transcoder/body.rb +3 -2
- data/lib/httpx/transcoder/chunker.rb +2 -1
- data/lib/httpx/transcoder/form.rb +20 -0
- data/lib/httpx/transcoder/json.rb +12 -0
- data/lib/httpx/transcoder.rb +62 -1
- data/lib/httpx/utils.rb +10 -2
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +7 -3
- data/sig/buffer.rbs +3 -1
- data/sig/chainable.rbs +31 -29
- data/sig/connection/http1.rbs +11 -5
- data/sig/connection/http2.rbs +16 -5
- data/sig/connection.rbs +31 -13
- data/sig/errors.rbs +35 -1
- data/sig/headers.rbs +20 -19
- data/sig/httpx.rbs +4 -1
- data/sig/loggable.rbs +3 -1
- data/sig/options.rbs +45 -34
- data/sig/parser/http1.rbs +3 -3
- data/sig/plugins/authentication.rbs +1 -1
- data/sig/plugins/aws_sdk_authentication.rbs +25 -3
- data/sig/plugins/aws_sigv4.rbs +13 -5
- data/sig/plugins/basic_authentication.rbs +1 -1
- data/sig/plugins/compression.rbs +4 -6
- data/sig/plugins/cookies/cookie.rbs +5 -7
- data/sig/plugins/cookies/jar.rbs +9 -10
- data/sig/plugins/cookies.rbs +4 -5
- data/sig/plugins/digest_authentication.rbs +2 -3
- data/sig/plugins/expect.rbs +2 -4
- data/sig/plugins/follow_redirects.rbs +3 -5
- data/sig/plugins/grpc.rbs +4 -7
- data/sig/plugins/h2c.rbs +0 -2
- data/sig/plugins/multipart.rbs +64 -10
- data/sig/plugins/ntlm_authentication.rbs +2 -3
- data/sig/plugins/persistent.rbs +3 -8
- data/sig/plugins/proxy/ssh.rbs +4 -4
- data/sig/plugins/proxy.rbs +13 -13
- data/sig/plugins/push_promise.rbs +0 -2
- data/sig/plugins/response_cache.rbs +35 -0
- data/sig/plugins/retries.rbs +7 -8
- data/sig/plugins/stream.rbs +1 -1
- data/sig/plugins/upgrade.rbs +2 -3
- data/sig/pool.rbs +7 -2
- data/sig/registry.rbs +1 -1
- data/sig/request.rbs +11 -8
- data/sig/resolver/native.rbs +10 -5
- data/sig/resolver/resolver_mixin.rbs +4 -5
- data/sig/resolver/system.rbs +4 -0
- data/sig/resolver.rbs +7 -0
- data/sig/response.rbs +26 -13
- data/sig/selector.rbs +11 -9
- data/sig/session.rbs +22 -23
- data/sig/timers.rbs +32 -0
- data/sig/transcoder/body.rbs +6 -1
- data/sig/transcoder/chunker.rbs +8 -2
- data/sig/transcoder/form.rbs +3 -1
- data/sig/transcoder/json.rbs +2 -0
- data/sig/transcoder.rbs +13 -5
- data/sig/utils.rbs +6 -0
- metadata +18 -18
- data/lib/httpx/request2.rb +0 -14
data/lib/httpx/connection.rb
CHANGED
|
@@ -69,10 +69,10 @@ module HTTPX
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
@inflight = 0
|
|
72
|
-
@keep_alive_timeout = options.timeout[:keep_alive_timeout]
|
|
73
|
-
@
|
|
72
|
+
@keep_alive_timeout = @options.timeout[:keep_alive_timeout]
|
|
73
|
+
@total_timeout = @options.timeout[:total_timeout]
|
|
74
74
|
|
|
75
|
-
self.addresses = options.addresses if options.addresses
|
|
75
|
+
self.addresses = @options.addresses if @options.addresses
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# this is a semi-private method, to be used by the resolver
|
|
@@ -200,11 +200,9 @@ module HTTPX
|
|
|
200
200
|
end
|
|
201
201
|
|
|
202
202
|
def close
|
|
203
|
-
|
|
204
|
-
return unless @keep_alive_timer
|
|
203
|
+
transition(:active) if @state == :inactive
|
|
205
204
|
|
|
206
|
-
@
|
|
207
|
-
remove_instance_variable(:@keep_alive_timer)
|
|
205
|
+
@parser.close if @parser
|
|
208
206
|
end
|
|
209
207
|
|
|
210
208
|
def reset
|
|
@@ -216,26 +214,40 @@ module HTTPX
|
|
|
216
214
|
def send(request)
|
|
217
215
|
if @parser && !@write_buffer.full?
|
|
218
216
|
request.headers["alt-used"] = @origin.authority if match_altsvcs?(request.uri)
|
|
219
|
-
|
|
217
|
+
|
|
218
|
+
if @response_received_at && @keep_alive_timeout &&
|
|
219
|
+
Utils.elapsed_time(@response_received_at) > @keep_alive_timeout
|
|
220
220
|
# when pushing a request into an existing connection, we have to check whether there
|
|
221
221
|
# is the possibility that the connection might have extended the keep alive timeout.
|
|
222
222
|
# for such cases, we want to ping for availability before deciding to shovel requests.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
@keep_alive_timer.pause
|
|
223
|
+
@pending << request
|
|
224
|
+
parser.ping
|
|
225
|
+
transition(:active) if @state == :inactive
|
|
226
|
+
return
|
|
230
227
|
end
|
|
231
|
-
|
|
232
|
-
|
|
228
|
+
|
|
229
|
+
send_request_to_parser(request)
|
|
233
230
|
else
|
|
234
231
|
@pending << request
|
|
235
232
|
end
|
|
236
233
|
end
|
|
237
234
|
|
|
238
235
|
def timeout
|
|
236
|
+
if @total_timeout
|
|
237
|
+
return @total_timeout unless @connected_at
|
|
238
|
+
|
|
239
|
+
elapsed_time = @total_timeout - Utils.elapsed_time(@connected_at)
|
|
240
|
+
|
|
241
|
+
if elapsed_time.negative?
|
|
242
|
+
ex = TotalTimeoutError.new(@total_timeout, "Timed out after #{@total_timeout} seconds")
|
|
243
|
+
ex.set_backtrace(caller)
|
|
244
|
+
on_error(@total_timeout)
|
|
245
|
+
return
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
return elapsed_time
|
|
249
|
+
end
|
|
250
|
+
|
|
239
251
|
return @timeout if defined?(@timeout)
|
|
240
252
|
|
|
241
253
|
return @options.timeout[:connect_timeout] if @state == :idle
|
|
@@ -243,6 +255,14 @@ module HTTPX
|
|
|
243
255
|
@options.timeout[:operation_timeout]
|
|
244
256
|
end
|
|
245
257
|
|
|
258
|
+
def deactivate
|
|
259
|
+
transition(:inactive)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def open?
|
|
263
|
+
@state == :open || @state == :inactive
|
|
264
|
+
end
|
|
265
|
+
|
|
246
266
|
private
|
|
247
267
|
|
|
248
268
|
def connect
|
|
@@ -313,7 +333,7 @@ module HTTPX
|
|
|
313
333
|
|
|
314
334
|
# exit #consume altogether if all outstanding requests have been dealt with
|
|
315
335
|
return if @pending.size.zero? && @inflight.zero?
|
|
316
|
-
end unless (interests.nil? ||
|
|
336
|
+
end unless ((ints = interests).nil? || ints == :w || @state == :closing) && !epiped
|
|
317
337
|
|
|
318
338
|
#
|
|
319
339
|
# tight write loop.
|
|
@@ -360,19 +380,18 @@ module HTTPX
|
|
|
360
380
|
break if interests == :r || @state == :closing || @state == :closed
|
|
361
381
|
|
|
362
382
|
write_drained = false
|
|
363
|
-
end unless interests == :r
|
|
383
|
+
end unless (ints = interests) == :r
|
|
364
384
|
|
|
365
385
|
send_pending if @state == :open
|
|
366
386
|
|
|
367
387
|
# return if socket is drained
|
|
368
|
-
next unless (
|
|
369
|
-
(interests != :w || write_drained)
|
|
388
|
+
next unless (ints != :r || read_drained) && (ints != :w || write_drained)
|
|
370
389
|
|
|
371
390
|
# gotta go back to the event loop. It happens when:
|
|
372
391
|
#
|
|
373
392
|
# * the socket is drained of bytes or it's not the interest of the conn to read;
|
|
374
393
|
# * theres nothing more to write, or it's not in the interest of the conn to write;
|
|
375
|
-
log(level: 3) { "(#{
|
|
394
|
+
log(level: 3) { "(#{ints}): WAITING FOR EVENTS..." }
|
|
376
395
|
return
|
|
377
396
|
end
|
|
378
397
|
end
|
|
@@ -380,9 +399,7 @@ module HTTPX
|
|
|
380
399
|
|
|
381
400
|
def send_pending
|
|
382
401
|
while !@write_buffer.full? && (request = @pending.shift)
|
|
383
|
-
|
|
384
|
-
@keep_alive_timer.pause if @keep_alive_timer
|
|
385
|
-
parser.send(request)
|
|
402
|
+
send_request_to_parser(request)
|
|
386
403
|
end
|
|
387
404
|
end
|
|
388
405
|
|
|
@@ -390,6 +407,15 @@ module HTTPX
|
|
|
390
407
|
@parser ||= build_parser
|
|
391
408
|
end
|
|
392
409
|
|
|
410
|
+
def send_request_to_parser(request)
|
|
411
|
+
@inflight += 1
|
|
412
|
+
parser.send(request)
|
|
413
|
+
|
|
414
|
+
return unless @state == :inactive
|
|
415
|
+
|
|
416
|
+
transition(:active)
|
|
417
|
+
end
|
|
418
|
+
|
|
393
419
|
def build_parser(protocol = @io.protocol)
|
|
394
420
|
parser = registry(protocol).new(@write_buffer, @options)
|
|
395
421
|
set_parser_callbacks(parser)
|
|
@@ -401,7 +427,8 @@ module HTTPX
|
|
|
401
427
|
AltSvc.emit(request, response) do |alt_origin, origin, alt_params|
|
|
402
428
|
emit(:altsvc, alt_origin, origin, alt_params)
|
|
403
429
|
end
|
|
404
|
-
|
|
430
|
+
@response_received_at = Utils.now
|
|
431
|
+
@inflight -= 1
|
|
405
432
|
request.emit(:response, response)
|
|
406
433
|
end
|
|
407
434
|
parser.on(:altsvc) do |alt_origin, origin, alt_params|
|
|
@@ -421,7 +448,7 @@ module HTTPX
|
|
|
421
448
|
end
|
|
422
449
|
parser.on(:close) do |force|
|
|
423
450
|
transition(:closing)
|
|
424
|
-
if force
|
|
451
|
+
if force || @state == :idle
|
|
425
452
|
transition(:closed)
|
|
426
453
|
emit(:close)
|
|
427
454
|
end
|
|
@@ -467,15 +494,17 @@ module HTTPX
|
|
|
467
494
|
when :open
|
|
468
495
|
return if @state == :closed
|
|
469
496
|
|
|
470
|
-
total_timeout
|
|
471
|
-
|
|
472
497
|
@io.connect
|
|
473
498
|
return unless @io.connected?
|
|
474
499
|
|
|
500
|
+
@connected_at = Utils.now
|
|
501
|
+
|
|
475
502
|
send_pending
|
|
476
503
|
|
|
477
504
|
@timeout = @current_timeout = parser.timeout
|
|
478
505
|
emit(:open)
|
|
506
|
+
when :inactive
|
|
507
|
+
return unless @state == :open
|
|
479
508
|
when :closing
|
|
480
509
|
return unless @state == :open
|
|
481
510
|
|
|
@@ -483,15 +512,15 @@ module HTTPX
|
|
|
483
512
|
return unless @state == :closing
|
|
484
513
|
return unless @write_buffer.empty?
|
|
485
514
|
|
|
486
|
-
if @total_timeout
|
|
487
|
-
@total_timeout.cancel
|
|
488
|
-
remove_instance_variable(:@total_timeout)
|
|
489
|
-
end
|
|
490
|
-
|
|
491
515
|
purge_after_closed
|
|
492
516
|
when :already_open
|
|
493
517
|
nextstate = :open
|
|
494
518
|
send_pending
|
|
519
|
+
when :active
|
|
520
|
+
return unless @state == :inactive
|
|
521
|
+
|
|
522
|
+
nextstate = :open
|
|
523
|
+
emit(:activate)
|
|
495
524
|
end
|
|
496
525
|
@state = nextstate
|
|
497
526
|
rescue Errno::ECONNREFUSED,
|
|
@@ -507,44 +536,24 @@ module HTTPX
|
|
|
507
536
|
def purge_after_closed
|
|
508
537
|
@io.close if @io
|
|
509
538
|
@read_buffer.clear
|
|
510
|
-
if @keep_alive_timer
|
|
511
|
-
@keep_alive_timer.cancel
|
|
512
|
-
remove_instance_variable(:@keep_alive_timer)
|
|
513
|
-
end
|
|
514
|
-
|
|
515
539
|
remove_instance_variable(:@timeout) if defined?(@timeout)
|
|
516
540
|
end
|
|
517
541
|
|
|
518
|
-
def handle_response
|
|
519
|
-
@inflight -= 1
|
|
520
|
-
return unless @inflight.zero?
|
|
521
|
-
|
|
522
|
-
if @keep_alive_timer
|
|
523
|
-
@keep_alive_timer.resume
|
|
524
|
-
@keep_alive_timer.reset
|
|
525
|
-
else
|
|
526
|
-
@keep_alive_timer = @timers.after(@keep_alive_timeout) do
|
|
527
|
-
unless @inflight.zero?
|
|
528
|
-
log { "(#{@origin}): keep alive timeout expired" }
|
|
529
|
-
parser.ping
|
|
530
|
-
end
|
|
531
|
-
end
|
|
532
|
-
end
|
|
533
|
-
end
|
|
534
|
-
|
|
535
542
|
def on_error(error)
|
|
536
543
|
if error.instance_of?(TimeoutError)
|
|
537
|
-
if @timeout
|
|
538
|
-
@timeout -= error.timeout
|
|
539
|
-
return unless @timeout <= 0
|
|
540
|
-
end
|
|
541
544
|
|
|
542
|
-
if @total_timeout && @
|
|
543
|
-
|
|
545
|
+
if @total_timeout && @connected_at &&
|
|
546
|
+
Utils.elapsed_time(@connected_at) > @total_timeout
|
|
547
|
+
ex = TotalTimeoutError.new(@total_timeout, "Timed out after #{@total_timeout} seconds")
|
|
544
548
|
ex.set_backtrace(error.backtrace)
|
|
545
549
|
error = ex
|
|
546
|
-
|
|
547
|
-
|
|
550
|
+
else
|
|
551
|
+
if @timeout
|
|
552
|
+
@timeout -= error.timeout
|
|
553
|
+
return unless @timeout <= 0
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
error = error.to_connection_error if connecting?
|
|
548
557
|
end
|
|
549
558
|
end
|
|
550
559
|
handle_error(error)
|
|
@@ -559,18 +568,5 @@ module HTTPX
|
|
|
559
568
|
request.emit(:response, response)
|
|
560
569
|
end
|
|
561
570
|
end
|
|
562
|
-
|
|
563
|
-
def total_timeout
|
|
564
|
-
total = @options.timeout[:total_timeout]
|
|
565
|
-
|
|
566
|
-
return unless total
|
|
567
|
-
|
|
568
|
-
@total_timeout ||= @timers.after(total) do
|
|
569
|
-
ex = TotalTimeoutError.new(total, "Timed out after #{total} seconds")
|
|
570
|
-
ex.set_backtrace(caller)
|
|
571
|
-
on_error(ex)
|
|
572
|
-
@parser.close if @parser
|
|
573
|
-
end
|
|
574
|
-
end
|
|
575
571
|
end
|
|
576
572
|
end
|
data/lib/httpx/domain_name.rb
CHANGED
data/lib/httpx/errors.rb
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module HTTPX
|
|
4
|
-
Error
|
|
4
|
+
class Error < StandardError; end
|
|
5
5
|
|
|
6
|
-
UnsupportedSchemeError
|
|
6
|
+
class UnsupportedSchemeError < Error; end
|
|
7
7
|
|
|
8
|
-
TimeoutError
|
|
8
|
+
class TimeoutError < Error
|
|
9
9
|
attr_reader :timeout
|
|
10
10
|
|
|
11
11
|
def initialize(timeout, message)
|
|
@@ -20,17 +20,17 @@ module HTTPX
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
TotalTimeoutError
|
|
23
|
+
class TotalTimeoutError < TimeoutError; end
|
|
24
24
|
|
|
25
|
-
ConnectTimeoutError
|
|
25
|
+
class ConnectTimeoutError < TimeoutError; end
|
|
26
26
|
|
|
27
|
-
SettingsTimeoutError
|
|
27
|
+
class SettingsTimeoutError < TimeoutError; end
|
|
28
28
|
|
|
29
|
-
ResolveTimeoutError
|
|
29
|
+
class ResolveTimeoutError < TimeoutError; end
|
|
30
30
|
|
|
31
|
-
ResolveError
|
|
31
|
+
class ResolveError < Error; end
|
|
32
32
|
|
|
33
|
-
NativeResolveError
|
|
33
|
+
class NativeResolveError < ResolveError
|
|
34
34
|
attr_reader :connection, :host
|
|
35
35
|
|
|
36
36
|
def initialize(connection, host, message = "Can't resolve #{host}")
|
|
@@ -40,7 +40,7 @@ module HTTPX
|
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
HTTPError
|
|
43
|
+
class HTTPError < Error
|
|
44
44
|
attr_reader :response
|
|
45
45
|
|
|
46
46
|
def initialize(response)
|
|
@@ -53,5 +53,5 @@ module HTTPX
|
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
MisdirectedRequestError
|
|
56
|
+
class MisdirectedRequestError < HTTPError; end
|
|
57
57
|
end
|
data/lib/httpx/extensions.rb
CHANGED
|
@@ -54,6 +54,51 @@ module HTTPX
|
|
|
54
54
|
Numeric.__send__(:include, NegMethods)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
module HashExtensions
|
|
58
|
+
refine Hash do
|
|
59
|
+
def compact
|
|
60
|
+
h = {}
|
|
61
|
+
each do |key, value|
|
|
62
|
+
h[key] = value unless value == nil
|
|
63
|
+
end
|
|
64
|
+
h
|
|
65
|
+
end unless Hash.method_defined?(:compact)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
module ArrayExtensions
|
|
70
|
+
refine Array do
|
|
71
|
+
|
|
72
|
+
def filter_map
|
|
73
|
+
return to_enum(:filter_map) unless block_given?
|
|
74
|
+
|
|
75
|
+
each_with_object([]) do |item, res|
|
|
76
|
+
processed = yield(item)
|
|
77
|
+
res << processed if processed
|
|
78
|
+
end
|
|
79
|
+
end unless Array.method_defined?(:filter_map)
|
|
80
|
+
|
|
81
|
+
def sum(accumulator = 0, &block)
|
|
82
|
+
values = block_given? ? map(&block) : self
|
|
83
|
+
values.inject(accumulator, :+)
|
|
84
|
+
end unless Array.method_defined?(:sum)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
module IOExtensions
|
|
89
|
+
refine IO do
|
|
90
|
+
# provides a fallback for rubies where IO#wait isn't implemented,
|
|
91
|
+
# but IO#wait_readable and IO#wait_writable are.
|
|
92
|
+
def wait(timeout = nil, _mode = :read_write)
|
|
93
|
+
r, w = IO.select([self], [self], nil, timeout)
|
|
94
|
+
|
|
95
|
+
return unless r || w
|
|
96
|
+
|
|
97
|
+
self
|
|
98
|
+
end unless IO.method_defined?(:wait) && IO.instance_method(:wait).arity == 2
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
57
102
|
module RegexpExtensions
|
|
58
103
|
# If you wonder why this is there: the oauth feature uses a refinement to enhance the
|
|
59
104
|
# Regexp class locally with #match? , but this is never tested, because ActiveSupport
|
|
@@ -77,13 +122,14 @@ module HTTPX
|
|
|
77
122
|
end
|
|
78
123
|
|
|
79
124
|
def authority
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
125
|
+
return host if port == default_port
|
|
126
|
+
|
|
127
|
+
"#{host}:#{port}"
|
|
128
|
+
end unless URI::HTTP.method_defined?(:authority)
|
|
83
129
|
|
|
84
130
|
def origin
|
|
85
131
|
"#{scheme}://#{authority}"
|
|
86
|
-
end
|
|
132
|
+
end unless URI::HTTP.method_defined?(:origin)
|
|
87
133
|
|
|
88
134
|
def altsvc_match?(uri)
|
|
89
135
|
uri = URI.parse(uri)
|
data/lib/httpx/headers.rb
CHANGED
data/lib/httpx/io/ssl.rb
CHANGED
|
@@ -7,9 +7,9 @@ module HTTPX
|
|
|
7
7
|
|
|
8
8
|
class SSL < TCP
|
|
9
9
|
TLS_OPTIONS = if OpenSSL::SSL::SSLContext.instance_methods.include?(:alpn_protocols)
|
|
10
|
-
{ alpn_protocols: %w[h2 http/1.1] }
|
|
10
|
+
{ alpn_protocols: %w[h2 http/1.1].freeze }.freeze
|
|
11
11
|
else
|
|
12
|
-
{}
|
|
12
|
+
{}.freeze
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def initialize(_, _, options)
|
|
@@ -134,7 +134,7 @@ module HTTPX
|
|
|
134
134
|
server_cert = @io.peer_cert
|
|
135
135
|
|
|
136
136
|
"#{super}\n\n" \
|
|
137
|
-
|
|
137
|
+
"SSL connection using #{@io.ssl_version} / #{Array(@io.cipher).first}\n" \
|
|
138
138
|
"ALPN, server accepted to use #{protocol}\n" \
|
|
139
139
|
"Server certificate:\n" \
|
|
140
140
|
" subject: #{server_cert.subject}\n" \
|
data/lib/httpx/io/tls.rb
CHANGED
|
@@ -4,7 +4,7 @@ require "openssl"
|
|
|
4
4
|
|
|
5
5
|
module HTTPX
|
|
6
6
|
class TLS < TCP
|
|
7
|
-
Error
|
|
7
|
+
class Error < StandardError; end
|
|
8
8
|
|
|
9
9
|
def initialize(_, _, options)
|
|
10
10
|
super
|
|
@@ -194,15 +194,15 @@ module HTTPX
|
|
|
194
194
|
server_cert = @peer_cert
|
|
195
195
|
|
|
196
196
|
"#{super}\n\n" \
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
"SSL connection using #{@ctx.ssl_version} / #{Array(@ctx.cipher).first}\n" \
|
|
198
|
+
"ALPN, server accepted to use #{protocol}\n" +
|
|
199
199
|
(if server_cert
|
|
200
200
|
"Server certificate:\n" \
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
201
|
+
" subject: #{server_cert.subject}\n" \
|
|
202
|
+
" start date: #{server_cert.not_before}\n" \
|
|
203
|
+
" expire date: #{server_cert.not_after}\n" \
|
|
204
|
+
" issuer: #{server_cert.issuer}\n" \
|
|
205
|
+
" SSL certificate verify ok."
|
|
206
206
|
else
|
|
207
207
|
"SSL certificate verify failed."
|
|
208
208
|
end
|
data/lib/httpx/loggable.rb
CHANGED
|
@@ -24,15 +24,13 @@ module HTTPX
|
|
|
24
24
|
debug_stream << message
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
if
|
|
27
|
+
if Exception.instance_methods.include?(:full_message)
|
|
28
28
|
|
|
29
29
|
def log_exception(ex, level: @options.debug_level, color: nil)
|
|
30
30
|
return unless @options.debug
|
|
31
31
|
return unless @options.debug_level >= level
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
message << "\n" << ex.backtrace.join("\n") unless ex.backtrace.nil?
|
|
35
|
-
log(level: level, color: color) { message }
|
|
33
|
+
log(level: level, color: color) { ex.full_message }
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
else
|
|
@@ -41,7 +39,9 @@ module HTTPX
|
|
|
41
39
|
return unless @options.debug
|
|
42
40
|
return unless @options.debug_level >= level
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
message = +"#{ex.message} (#{ex.class})"
|
|
43
|
+
message << "\n" << ex.backtrace.join("\n") unless ex.backtrace.nil?
|
|
44
|
+
log(level: level, color: color) { message }
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
end
|