httpx 1.5.1 → 1.6.1
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/doc/release_notes/1_6_1.md +17 -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 +34 -18
- data/lib/httpx/connection.rb +19 -26
- data/lib/httpx/errors.rb +3 -1
- data/lib/httpx/io/ssl.rb +1 -4
- data/lib/httpx/io/tcp.rb +52 -21
- data/lib/httpx/io/unix.rb +4 -3
- data/lib/httpx/loggable.rb +4 -1
- data/lib/httpx/options.rb +248 -160
- 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 +10 -2
- 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 +16 -3
- data/lib/httpx/resolver/native.rb +15 -6
- data/lib/httpx/resolver/resolver.rb +15 -11
- data/lib/httpx/resolver/system.rb +5 -3
- data/lib/httpx/resolver.rb +49 -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 +5 -1
- 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 +64 -11
- data/sig/plugins/fiber_concurrency.rbs +51 -0
- data/sig/plugins/h2c.rbs +5 -1
- data/sig/plugins/oauth.rbs +15 -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 +12 -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 +11 -3
data/lib/httpx/io/tcp.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "resolv"
|
4
|
-
require "ipaddr"
|
5
4
|
|
6
5
|
module HTTPX
|
7
6
|
class TCP
|
@@ -15,7 +14,10 @@ module HTTPX
|
|
15
14
|
|
16
15
|
def initialize(origin, addresses, options)
|
17
16
|
@state = :idle
|
17
|
+
@keep_open = false
|
18
18
|
@addresses = []
|
19
|
+
@ip_index = -1
|
20
|
+
@ip = nil
|
19
21
|
@hostname = origin.host
|
20
22
|
@options = options
|
21
23
|
@fallback_protocol = @options.fallback_protocol
|
@@ -30,7 +32,8 @@ module HTTPX
|
|
30
32
|
end
|
31
33
|
raise Error, "Given IO objects do not match the request authority" unless @io
|
32
34
|
|
33
|
-
_, _, _,
|
35
|
+
_, _, _, ip = @io.addr
|
36
|
+
@ip = Resolver::Entry.new(ip)
|
34
37
|
@addresses << @ip
|
35
38
|
@keep_open = true
|
36
39
|
@state = :connected
|
@@ -47,16 +50,31 @@ module HTTPX
|
|
47
50
|
def add_addresses(addrs)
|
48
51
|
return if addrs.empty?
|
49
52
|
|
50
|
-
addrs = addrs.map { |addr| addr.is_a?(IPAddr) ? addr : IPAddr.new(addr) }
|
51
|
-
|
52
53
|
ip_index = @ip_index || (@addresses.size - 1)
|
53
54
|
if addrs.first.ipv6?
|
54
55
|
# should be the next in line
|
55
56
|
@addresses = [*@addresses[0, ip_index], *addrs, *@addresses[ip_index..-1]]
|
56
57
|
else
|
57
58
|
@addresses.unshift(*addrs)
|
58
|
-
@ip_index += addrs.size if @ip_index
|
59
59
|
end
|
60
|
+
@ip_index += addrs.size
|
61
|
+
end
|
62
|
+
|
63
|
+
# eliminates expired entries and returns whether there are still any left.
|
64
|
+
def addresses?
|
65
|
+
prev_addr_size = @addresses.size
|
66
|
+
|
67
|
+
@addresses.delete_if(&:expired?).sort! do |addr1, addr2|
|
68
|
+
if addr1.ipv6?
|
69
|
+
addr2.ipv6? ? 0 : 1
|
70
|
+
else
|
71
|
+
addr2.ipv6? ? -1 : 0
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
@ip_index = @addresses.size - 1 if prev_addr_size != @addresses.size
|
76
|
+
|
77
|
+
@addresses.any?
|
60
78
|
end
|
61
79
|
|
62
80
|
def to_io
|
@@ -70,27 +88,51 @@ module HTTPX
|
|
70
88
|
def connect
|
71
89
|
return unless closed?
|
72
90
|
|
91
|
+
if @addresses.empty?
|
92
|
+
# an idle connection trying to connect with no available addresses is a connection
|
93
|
+
# out of the initial context which is back to the DNS resolution loop. This may
|
94
|
+
# happen in a fiber-aware context where a connection reconnects with expired addresses,
|
95
|
+
# and context is passed back to a fiber on the same connection while waiting for the
|
96
|
+
# DNS answer.
|
97
|
+
log { "tried connecting while resolving, skipping..." }
|
98
|
+
|
99
|
+
return
|
100
|
+
end
|
101
|
+
|
73
102
|
if !@io || @io.closed?
|
74
103
|
transition(:idle)
|
75
104
|
@io = build_socket
|
76
105
|
end
|
77
106
|
try_connect
|
107
|
+
rescue Errno::EHOSTUNREACH,
|
108
|
+
Errno::ENETUNREACH => e
|
109
|
+
@ip_index -= 1
|
110
|
+
|
111
|
+
raise e if @ip_index.negative?
|
112
|
+
|
113
|
+
log { "failed connecting to #{@ip} (#{e.message}), evict from cache and trying next..." }
|
114
|
+
Resolver.cached_lookup_evict(@hostname, @ip)
|
115
|
+
|
116
|
+
@io = build_socket
|
117
|
+
retry
|
78
118
|
rescue Errno::ECONNREFUSED,
|
79
119
|
Errno::EADDRNOTAVAIL,
|
80
|
-
Errno::EHOSTUNREACH,
|
81
120
|
SocketError,
|
82
121
|
IOError => e
|
83
|
-
|
122
|
+
@ip_index -= 1
|
123
|
+
|
124
|
+
raise e if @ip_index.negative?
|
84
125
|
|
85
126
|
log { "failed connecting to #{@ip} (#{e.message}), trying next..." }
|
86
|
-
@ip_index -= 1
|
87
127
|
@io = build_socket
|
88
128
|
retry
|
89
129
|
rescue Errno::ETIMEDOUT => e
|
90
|
-
|
130
|
+
@ip_index -= 1
|
131
|
+
|
132
|
+
raise ConnectTimeoutError.new(@options.timeout[:connect_timeout], e.message) if @ip_index.negative?
|
91
133
|
|
92
134
|
log { "failed connecting to #{@ip} (#{e.message}), trying next..." }
|
93
|
-
|
135
|
+
|
94
136
|
@io = build_socket
|
95
137
|
retry
|
96
138
|
end
|
@@ -154,17 +196,6 @@ module HTTPX
|
|
154
196
|
@state == :idle || @state == :closed
|
155
197
|
end
|
156
198
|
|
157
|
-
def expired?
|
158
|
-
# do not mess with external sockets
|
159
|
-
return false if @options.io
|
160
|
-
|
161
|
-
return true unless @addresses
|
162
|
-
|
163
|
-
resolver_addresses = Resolver.nolookup_resolve(@hostname)
|
164
|
-
|
165
|
-
(Array(resolver_addresses) & @addresses).empty?
|
166
|
-
end
|
167
|
-
|
168
199
|
# :nocov:
|
169
200
|
def inspect
|
170
201
|
"#<#{self.class}:#{object_id} " \
|
data/lib/httpx/io/unix.rb
CHANGED
@@ -48,11 +48,12 @@ module HTTPX
|
|
48
48
|
transition(:connected)
|
49
49
|
rescue Errno::EINPROGRESS,
|
50
50
|
Errno::EALREADY,
|
51
|
-
|
51
|
+
IO::WaitReadable
|
52
52
|
end
|
53
53
|
|
54
|
-
|
55
|
-
|
54
|
+
# the path is always explicitly passed, so no point in resolving.
|
55
|
+
def addresses?
|
56
|
+
true
|
56
57
|
end
|
57
58
|
|
58
59
|
# :nocov:
|
data/lib/httpx/loggable.rb
CHANGED
@@ -34,7 +34,10 @@ module HTTPX
|
|
34
34
|
klass = klass.superclass
|
35
35
|
end
|
36
36
|
|
37
|
-
message = +"(pid:#{Process.pid}
|
37
|
+
message = +"(pid:#{Process.pid}, " \
|
38
|
+
"tid:#{Thread.current.object_id}, " \
|
39
|
+
"fid:#{Fiber.current.object_id}, " \
|
40
|
+
"self:#{class_name}##{object_id}) "
|
38
41
|
message << msg.call << "\n"
|
39
42
|
message = "\e[#{COLORS[color]}m#{message}\e[0m" if color && debug_stream.respond_to?(:isatty) && debug_stream.isatty
|
40
43
|
debug_stream << message
|