httpx 1.2.6 → 1.4.4
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/README.md +1 -2
- data/doc/release_notes/1_3_0.md +18 -0
- data/doc/release_notes/1_3_1.md +17 -0
- data/doc/release_notes/1_3_2.md +6 -0
- data/doc/release_notes/1_3_3.md +5 -0
- data/doc/release_notes/1_3_4.md +6 -0
- data/doc/release_notes/1_4_0.md +43 -0
- data/doc/release_notes/1_4_1.md +19 -0
- data/doc/release_notes/1_4_2.md +20 -0
- data/doc/release_notes/1_4_3.md +11 -0
- data/doc/release_notes/1_4_4.md +14 -0
- data/lib/httpx/adapters/datadog.rb +56 -80
- data/lib/httpx/adapters/faraday.rb +5 -2
- data/lib/httpx/adapters/webmock.rb +24 -8
- data/lib/httpx/callbacks.rb +2 -7
- data/lib/httpx/chainable.rb +3 -1
- data/lib/httpx/connection/http1.rb +11 -7
- data/lib/httpx/connection/http2.rb +57 -34
- data/lib/httpx/connection.rb +270 -71
- data/lib/httpx/errors.rb +15 -4
- data/lib/httpx/io/ssl.rb +6 -3
- data/lib/httpx/io/tcp.rb +1 -1
- data/lib/httpx/io/unix.rb +1 -1
- data/lib/httpx/loggable.rb +17 -10
- data/lib/httpx/options.rb +30 -23
- data/lib/httpx/plugins/aws_sdk_authentication.rb +3 -0
- data/lib/httpx/plugins/aws_sigv4.rb +36 -17
- data/lib/httpx/plugins/callbacks.rb +13 -2
- data/lib/httpx/plugins/circuit_breaker.rb +11 -5
- data/lib/httpx/plugins/content_digest.rb +202 -0
- data/lib/httpx/plugins/cookies.rb +9 -6
- data/lib/httpx/plugins/digest_auth.rb +3 -0
- data/lib/httpx/plugins/expect.rb +10 -4
- data/lib/httpx/plugins/follow_redirects.rb +68 -33
- data/lib/httpx/plugins/grpc/grpc_encoding.rb +2 -0
- data/lib/httpx/plugins/grpc.rb +2 -2
- data/lib/httpx/plugins/h2c.rb +23 -20
- data/lib/httpx/plugins/internal_telemetry.rb +48 -1
- data/lib/httpx/plugins/oauth.rb +1 -1
- data/lib/httpx/plugins/persistent.rb +16 -0
- data/lib/httpx/plugins/proxy/http.rb +19 -16
- data/lib/httpx/plugins/proxy/socks4.rb +1 -1
- data/lib/httpx/plugins/proxy/socks5.rb +1 -1
- data/lib/httpx/plugins/proxy.rb +96 -85
- data/lib/httpx/plugins/retries.rb +28 -10
- data/lib/httpx/plugins/ssrf_filter.rb +4 -1
- data/lib/httpx/plugins/stream.rb +42 -18
- data/lib/httpx/plugins/upgrade.rb +5 -10
- data/lib/httpx/plugins/webdav.rb +6 -0
- data/lib/httpx/plugins/xml.rb +76 -0
- data/lib/httpx/pool.rb +73 -244
- data/lib/httpx/request/body.rb +50 -55
- data/lib/httpx/request.rb +77 -14
- data/lib/httpx/resolver/https.rb +17 -20
- data/lib/httpx/resolver/multi.rb +34 -16
- data/lib/httpx/resolver/native.rb +140 -61
- data/lib/httpx/resolver/resolver.rb +64 -19
- data/lib/httpx/resolver/system.rb +32 -16
- data/lib/httpx/resolver.rb +21 -14
- data/lib/httpx/response/body.rb +12 -1
- data/lib/httpx/response.rb +16 -9
- data/lib/httpx/selector.rb +170 -91
- data/lib/httpx/session.rb +282 -139
- data/lib/httpx/timers.rb +17 -2
- data/lib/httpx/transcoder/body.rb +15 -29
- data/lib/httpx/transcoder/form.rb +2 -0
- data/lib/httpx/transcoder/gzip.rb +0 -3
- data/lib/httpx/transcoder/json.rb +16 -2
- data/lib/httpx/transcoder/multipart/encoder.rb +11 -2
- data/lib/httpx/transcoder/multipart/part.rb +1 -1
- data/lib/httpx/transcoder/utils/deflater.rb +7 -4
- data/lib/httpx/transcoder.rb +0 -1
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +20 -21
- data/sig/callbacks.rbs +2 -3
- data/sig/chainable.rbs +6 -2
- data/sig/connection/http1.rbs +2 -2
- data/sig/connection/http2.rbs +22 -18
- data/sig/connection.rbs +40 -9
- data/sig/errors.rbs +9 -3
- data/sig/httpx.rbs +3 -3
- data/sig/io/tcp.rbs +1 -1
- data/sig/io/unix.rbs +1 -1
- data/sig/loggable.rbs +4 -2
- data/sig/options.rbs +8 -13
- data/sig/plugins/aws_sigv4.rbs +8 -2
- data/sig/plugins/content_digest.rbs +51 -0
- data/sig/plugins/cookies/cookie.rbs +9 -0
- data/sig/plugins/follow_redirects.rbs +1 -1
- data/sig/plugins/grpc/call.rbs +4 -0
- data/sig/plugins/persistent.rbs +4 -1
- data/sig/plugins/proxy/http.rbs +3 -0
- data/sig/plugins/proxy/socks5.rbs +11 -3
- data/sig/plugins/proxy.rbs +18 -9
- data/sig/plugins/push_promise.rbs +6 -3
- data/sig/plugins/rate_limiter.rbs +2 -0
- data/sig/plugins/retries.rbs +1 -1
- data/sig/plugins/ssrf_filter.rbs +26 -0
- data/sig/plugins/stream.rbs +3 -0
- data/sig/plugins/webdav.rbs +23 -0
- data/sig/plugins/xml.rbs +37 -0
- data/sig/pool.rbs +27 -33
- data/sig/request/body.rbs +4 -10
- data/sig/request.rbs +14 -1
- data/sig/resolver/multi.rbs +26 -1
- data/sig/resolver/native.rbs +6 -3
- data/sig/resolver/resolver.rbs +22 -3
- data/sig/resolver.rbs +5 -1
- data/sig/response/body.rbs +2 -2
- data/sig/response/buffer.rbs +2 -2
- data/sig/response.rbs +9 -4
- data/sig/selector.rbs +31 -4
- data/sig/session.rbs +54 -20
- data/sig/timers.rbs +15 -4
- data/sig/transcoder/body.rbs +2 -4
- data/sig/transcoder/chunker.rbs +1 -1
- data/sig/transcoder/deflate.rbs +1 -0
- data/sig/transcoder/form.rbs +8 -0
- data/sig/transcoder/gzip.rbs +4 -1
- data/sig/transcoder/json.rbs +1 -1
- data/sig/transcoder/multipart.rbs +6 -4
- data/sig/transcoder/utils/body_reader.rbs +3 -3
- data/sig/transcoder/utils/deflater.rbs +2 -3
- metadata +32 -14
- data/lib/httpx/session2.rb +0 -23
- data/lib/httpx/transcoder/utils/inflater.rb +0 -19
- data/lib/httpx/transcoder/xml.rb +0 -52
- data/sig/transcoder/utils/inflater.rbs +0 -12
- data/sig/transcoder/xml.rbs +0 -22
data/lib/httpx/request.rb
CHANGED
@@ -11,8 +11,10 @@ module HTTPX
|
|
11
11
|
include Callbacks
|
12
12
|
using URIExtensions
|
13
13
|
|
14
|
+
ALLOWED_URI_SCHEMES = %w[https http].freeze
|
15
|
+
|
14
16
|
# default value used for "user-agent" header, when not overridden.
|
15
|
-
USER_AGENT = "httpx.rb/#{VERSION}"
|
17
|
+
USER_AGENT = "httpx.rb/#{VERSION}".freeze # rubocop:disable Style/RedundantFreeze
|
16
18
|
|
17
19
|
# the upcased string HTTP verb for this request.
|
18
20
|
attr_reader :verb
|
@@ -43,16 +45,52 @@ module HTTPX
|
|
43
45
|
|
44
46
|
attr_writer :persistent
|
45
47
|
|
48
|
+
attr_reader :active_timeouts
|
49
|
+
|
46
50
|
# will be +true+ when request body has been completely flushed.
|
47
51
|
def_delegator :@body, :empty?
|
48
52
|
|
49
|
-
#
|
50
|
-
|
51
|
-
|
53
|
+
# closes the body
|
54
|
+
def_delegator :@body, :close
|
55
|
+
|
56
|
+
# initializes the instance with the given +verb+ (an upppercase String, ex. 'GEt'),
|
57
|
+
# an absolute or relative +uri+ (either as String or URI::HTTP object), the
|
58
|
+
# request +options+ (instance of HTTPX::Options) and an optional Hash of +params+.
|
59
|
+
#
|
60
|
+
# Besides any of the options documented in HTTPX::Options (which would override or merge with what
|
61
|
+
# +options+ sets), it accepts also the following:
|
62
|
+
#
|
63
|
+
# :params :: hash or array of key-values which will be encoded and set in the query string of request uris.
|
64
|
+
# :body :: to be encoded in the request body payload. can be a String, an IO object (i.e. a File), or an Enumerable.
|
65
|
+
# :form :: hash of array of key-values which will be form-urlencoded- or multipart-encoded in requests body payload.
|
66
|
+
# :json :: hash of array of key-values which will be JSON-encoded in requests body payload.
|
67
|
+
# :xml :: Nokogiri XML nodes which will be encoded in requests body payload.
|
68
|
+
#
|
69
|
+
# :body, :form, :json and :xml are all mutually exclusive, i.e. only one of them gets picked up.
|
70
|
+
def initialize(verb, uri, options, params = EMPTY_HASH)
|
52
71
|
@verb = verb.to_s.upcase
|
53
|
-
@options = Options.new(options)
|
54
72
|
@uri = Utils.to_uri(uri)
|
55
|
-
|
73
|
+
|
74
|
+
@headers = options.headers.dup
|
75
|
+
merge_headers(params.delete(:headers)) if params.key?(:headers)
|
76
|
+
|
77
|
+
@headers["user-agent"] ||= USER_AGENT
|
78
|
+
@headers["accept"] ||= "*/*"
|
79
|
+
|
80
|
+
# forego compression in the Range request case
|
81
|
+
if @headers.key?("range")
|
82
|
+
@headers.delete("accept-encoding")
|
83
|
+
else
|
84
|
+
@headers["accept-encoding"] ||= options.supported_compression_formats
|
85
|
+
end
|
86
|
+
|
87
|
+
@query_params = params.delete(:params) if params.key?(:params)
|
88
|
+
|
89
|
+
@body = options.request_body_class.new(@headers, options, **params)
|
90
|
+
|
91
|
+
@options = @body.options
|
92
|
+
|
93
|
+
if @uri.relative? || @uri.host.nil?
|
56
94
|
origin = @options.origin
|
57
95
|
raise(Error, "invalid URI: #{@uri}") unless origin
|
58
96
|
|
@@ -61,28 +99,37 @@ module HTTPX
|
|
61
99
|
@uri = origin.merge("#{base_path}#{@uri}")
|
62
100
|
end
|
63
101
|
|
64
|
-
@
|
65
|
-
@headers["user-agent"] ||= USER_AGENT
|
66
|
-
@headers["accept"] ||= "*/*"
|
102
|
+
raise UnsupportedSchemeError, "#{@uri}: #{@uri.scheme}: unsupported URI scheme" unless ALLOWED_URI_SCHEMES.include?(@uri.scheme)
|
67
103
|
|
68
|
-
@body = @options.request_body_class.new(@headers, @options)
|
69
104
|
@state = :idle
|
70
105
|
@response = nil
|
71
106
|
@peer_address = nil
|
107
|
+
@ping = false
|
72
108
|
@persistent = @options.persistent
|
109
|
+
@active_timeouts = []
|
110
|
+
end
|
111
|
+
|
112
|
+
# whether request has been buffered with a ping
|
113
|
+
def ping?
|
114
|
+
@ping
|
115
|
+
end
|
116
|
+
|
117
|
+
# marks the request as having been buffered with a ping
|
118
|
+
def ping!
|
119
|
+
@ping = true
|
73
120
|
end
|
74
121
|
|
75
|
-
# the read timeout
|
122
|
+
# the read timeout defined for this request.
|
76
123
|
def read_timeout
|
77
124
|
@options.timeout[:read_timeout]
|
78
125
|
end
|
79
126
|
|
80
|
-
# the write timeout
|
127
|
+
# the write timeout defined for this request.
|
81
128
|
def write_timeout
|
82
129
|
@options.timeout[:write_timeout]
|
83
130
|
end
|
84
131
|
|
85
|
-
# the request timeout
|
132
|
+
# the request timeout defined for this request.
|
86
133
|
def request_timeout
|
87
134
|
@options.timeout[:request_timeout]
|
88
135
|
end
|
@@ -91,10 +138,12 @@ module HTTPX
|
|
91
138
|
@persistent
|
92
139
|
end
|
93
140
|
|
141
|
+
# if the request contains trailer headers
|
94
142
|
def trailers?
|
95
143
|
defined?(@trailers)
|
96
144
|
end
|
97
145
|
|
146
|
+
# returns an instance of HTTPX::Headers containing the trailer headers
|
98
147
|
def trailers
|
99
148
|
@trailers ||= @options.headers_class.new
|
100
149
|
end
|
@@ -106,6 +155,7 @@ module HTTPX
|
|
106
155
|
:w
|
107
156
|
end
|
108
157
|
|
158
|
+
# merges +h+ into the instance of HTTPX::Headers of the request.
|
109
159
|
def merge_headers(h)
|
110
160
|
@headers = @headers.merge(h)
|
111
161
|
end
|
@@ -172,7 +222,7 @@ module HTTPX
|
|
172
222
|
return @query if defined?(@query)
|
173
223
|
|
174
224
|
query = []
|
175
|
-
if (q = @
|
225
|
+
if (q = @query_params)
|
176
226
|
query << Transcoder::Form.encode(q)
|
177
227
|
end
|
178
228
|
query << @uri.query if @uri.query
|
@@ -210,10 +260,13 @@ module HTTPX
|
|
210
260
|
case nextstate
|
211
261
|
when :idle
|
212
262
|
@body.rewind
|
263
|
+
@ping = false
|
213
264
|
@response = nil
|
214
265
|
@drainer = nil
|
266
|
+
@active_timeouts.clear
|
215
267
|
when :headers
|
216
268
|
return unless @state == :idle
|
269
|
+
|
217
270
|
when :body
|
218
271
|
return unless @state == :headers ||
|
219
272
|
@state == :expect
|
@@ -234,6 +287,7 @@ module HTTPX
|
|
234
287
|
return unless @state == :body
|
235
288
|
when :done
|
236
289
|
return if @state == :expect
|
290
|
+
|
237
291
|
end
|
238
292
|
@state = nextstate
|
239
293
|
emit(@state, self)
|
@@ -244,6 +298,15 @@ module HTTPX
|
|
244
298
|
def expects?
|
245
299
|
@headers["expect"] == "100-continue" && @informational_status == 100 && !@response
|
246
300
|
end
|
301
|
+
|
302
|
+
def set_timeout_callback(event, &callback)
|
303
|
+
clb = once(event, &callback)
|
304
|
+
|
305
|
+
# reset timeout callbacks when requests get rerouted to a different connection
|
306
|
+
once(:idle) do
|
307
|
+
callbacks(event).delete(clb)
|
308
|
+
end
|
309
|
+
end
|
247
310
|
end
|
248
311
|
end
|
249
312
|
|
data/lib/httpx/resolver/https.rb
CHANGED
@@ -27,7 +27,7 @@ module HTTPX
|
|
27
27
|
use_get: false,
|
28
28
|
}.freeze
|
29
29
|
|
30
|
-
def_delegators :@resolver_connection, :state, :connecting?, :to_io, :call, :close, :terminate
|
30
|
+
def_delegators :@resolver_connection, :state, :connecting?, :to_io, :call, :close, :terminate, :inflight?
|
31
31
|
|
32
32
|
def initialize(_, options)
|
33
33
|
super
|
@@ -43,7 +43,7 @@ module HTTPX
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def <<(connection)
|
46
|
-
return if @uri.origin == connection.
|
46
|
+
return if @uri.origin == connection.peer.to_s
|
47
47
|
|
48
48
|
@uri_addresses ||= HTTPX::Resolver.nolookup_resolve(@uri.host) || @resolver.getaddresses(@uri.host)
|
49
49
|
|
@@ -66,28 +66,25 @@ module HTTPX
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def resolver_connection
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
# only explicity emit addresses if connection didn't pre-resolve, i.e. it's not an IP.
|
74
|
-
emit_addresses(connection, @family, @uri_addresses) unless connection.addresses
|
75
|
-
@building_connection = false
|
76
|
-
connection
|
69
|
+
# TODO: leaks connection object into the pool
|
70
|
+
@resolver_connection ||= @current_session.find_connection(@uri, @current_selector,
|
71
|
+
@options.merge(ssl: { alpn_protocols: %w[h2] })).tap do |conn|
|
72
|
+
emit_addresses(conn, @family, @uri_addresses) unless conn.addresses
|
77
73
|
end
|
78
74
|
end
|
79
75
|
|
80
76
|
private
|
81
77
|
|
82
78
|
def resolve(connection = @connections.first, hostname = nil)
|
83
|
-
return if @building_connection
|
84
79
|
return unless connection
|
85
80
|
|
86
81
|
hostname ||= @queries.key(connection)
|
87
82
|
|
88
83
|
if hostname.nil?
|
89
|
-
hostname = connection.
|
90
|
-
log
|
84
|
+
hostname = connection.peer.host
|
85
|
+
log do
|
86
|
+
"resolver #{FAMILY_TYPES[@record_type]}: resolve IDN #{connection.peer.non_ascii_hostname} as #{hostname}"
|
87
|
+
end if connection.peer.non_ascii_hostname
|
91
88
|
|
92
89
|
hostname = @resolver.generate_candidates(hostname).each do |name|
|
93
90
|
@queries[name.to_s] = connection
|
@@ -95,7 +92,7 @@ module HTTPX
|
|
95
92
|
else
|
96
93
|
@queries[hostname] = connection
|
97
94
|
end
|
98
|
-
log { "resolver
|
95
|
+
log { "resolver #{FAMILY_TYPES[@record_type]}: query for #{hostname}" }
|
99
96
|
|
100
97
|
begin
|
101
98
|
request = build_request(hostname)
|
@@ -106,7 +103,7 @@ module HTTPX
|
|
106
103
|
@connections << connection
|
107
104
|
rescue ResolveError, Resolv::DNS::EncodeError => e
|
108
105
|
reset_hostname(hostname)
|
109
|
-
emit_resolve_error(connection, connection.
|
106
|
+
emit_resolve_error(connection, connection.peer.host, e)
|
110
107
|
end
|
111
108
|
end
|
112
109
|
|
@@ -115,7 +112,7 @@ module HTTPX
|
|
115
112
|
rescue StandardError => e
|
116
113
|
hostname = @requests.delete(request)
|
117
114
|
connection = reset_hostname(hostname)
|
118
|
-
emit_resolve_error(connection, connection.
|
115
|
+
emit_resolve_error(connection, connection.peer.host, e)
|
119
116
|
else
|
120
117
|
# @type var response: HTTPX::Response
|
121
118
|
parse(request, response)
|
@@ -154,7 +151,7 @@ module HTTPX
|
|
154
151
|
when :decode_error
|
155
152
|
host = @requests.delete(request)
|
156
153
|
connection = reset_hostname(host)
|
157
|
-
emit_resolve_error(connection, connection.
|
154
|
+
emit_resolve_error(connection, connection.peer.host, result)
|
158
155
|
end
|
159
156
|
end
|
160
157
|
|
@@ -174,7 +171,7 @@ module HTTPX
|
|
174
171
|
alias_address = answers[address["alias"]]
|
175
172
|
if alias_address.nil?
|
176
173
|
reset_hostname(address["name"])
|
177
|
-
if
|
174
|
+
if early_resolve(connection, hostname: address["alias"])
|
178
175
|
@connections.delete(connection)
|
179
176
|
else
|
180
177
|
resolve(connection, address["alias"])
|
@@ -199,7 +196,7 @@ module HTTPX
|
|
199
196
|
@queries.delete_if { |_, conn| connection == conn }
|
200
197
|
|
201
198
|
Resolver.cached_lookup_set(hostname, @family, addresses) if @resolver_options[:cache]
|
202
|
-
emit_addresses(connection, @family, addresses.map { |addr| addr["data"] })
|
199
|
+
catch(:coalesced) { emit_addresses(connection, @family, addresses.map { |addr| addr["data"] }) }
|
203
200
|
end
|
204
201
|
end
|
205
202
|
return if @connections.empty?
|
@@ -219,7 +216,7 @@ module HTTPX
|
|
219
216
|
uri.query = URI.encode_www_form(params)
|
220
217
|
request = rklass.new("GET", uri, @options)
|
221
218
|
else
|
222
|
-
request = rklass.new("POST", uri, @options
|
219
|
+
request = rklass.new("POST", uri, @options, body: [payload])
|
223
220
|
request.headers["content-type"] = "application/dns-message"
|
224
221
|
end
|
225
222
|
request.headers["accept"] = "application/dns-message"
|
data/lib/httpx/resolver/multi.rb
CHANGED
@@ -8,27 +8,45 @@ module HTTPX
|
|
8
8
|
include Callbacks
|
9
9
|
using ArrayExtensions::FilterMap
|
10
10
|
|
11
|
-
attr_reader :resolvers
|
11
|
+
attr_reader :resolvers, :options
|
12
12
|
|
13
13
|
def initialize(resolver_type, options)
|
14
|
+
@current_selector = nil
|
15
|
+
@current_session = nil
|
14
16
|
@options = options
|
15
17
|
@resolver_options = @options.resolver_options
|
16
18
|
|
17
19
|
@resolvers = options.ip_families.map do |ip_family|
|
18
20
|
resolver = resolver_type.new(ip_family, options)
|
19
|
-
resolver.
|
20
|
-
resolver.on(:error, &method(:on_resolver_error))
|
21
|
-
resolver.on(:close) { on_resolver_close(resolver) }
|
21
|
+
resolver.multi = self
|
22
22
|
resolver
|
23
23
|
end
|
24
24
|
|
25
25
|
@errors = Hash.new { |hs, k| hs[k] = [] }
|
26
26
|
end
|
27
27
|
|
28
|
+
def current_selector=(s)
|
29
|
+
@current_selector = s
|
30
|
+
@resolvers.each { |r| r.__send__(__method__, s) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def current_session=(s)
|
34
|
+
@current_session = s
|
35
|
+
@resolvers.each { |r| r.__send__(__method__, s) }
|
36
|
+
end
|
37
|
+
|
28
38
|
def closed?
|
29
39
|
@resolvers.all?(&:closed?)
|
30
40
|
end
|
31
41
|
|
42
|
+
def empty?
|
43
|
+
@resolvers.all?(&:empty?)
|
44
|
+
end
|
45
|
+
|
46
|
+
def inflight?
|
47
|
+
@resolvers.any(&:inflight?)
|
48
|
+
end
|
49
|
+
|
32
50
|
def timeout
|
33
51
|
@resolvers.filter_map(&:timeout).min
|
34
52
|
end
|
@@ -42,10 +60,11 @@ module HTTPX
|
|
42
60
|
end
|
43
61
|
|
44
62
|
def early_resolve(connection)
|
45
|
-
hostname = connection.
|
63
|
+
hostname = connection.peer.host
|
46
64
|
addresses = @resolver_options[:cache] && (connection.addresses || HTTPX::Resolver.nolookup_resolve(hostname))
|
47
|
-
return unless addresses
|
65
|
+
return false unless addresses
|
48
66
|
|
67
|
+
resolved = false
|
49
68
|
addresses.group_by(&:family).sort { |(f1, _), (f2, _)| f2 <=> f1 }.each do |family, addrs|
|
50
69
|
# try to match the resolver by family. However, there are cases where that's not possible, as when
|
51
70
|
# the system does not have IPv6 connectivity, but it does support IPv6 via loopback/link-local.
|
@@ -55,21 +74,20 @@ module HTTPX
|
|
55
74
|
|
56
75
|
# it does not matter which resolver it is, as early-resolve code is shared.
|
57
76
|
resolver.emit_addresses(connection, family, addrs, true)
|
58
|
-
end
|
59
|
-
end
|
60
77
|
|
61
|
-
|
78
|
+
resolved = true
|
79
|
+
end
|
62
80
|
|
63
|
-
|
64
|
-
emit(:resolve, connection)
|
81
|
+
resolved
|
65
82
|
end
|
66
83
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
84
|
+
def lazy_resolve(connection)
|
85
|
+
@resolvers.each do |resolver|
|
86
|
+
resolver << @current_session.try_clone_connection(connection, @current_selector, resolver.family)
|
87
|
+
next if resolver.empty?
|
70
88
|
|
71
|
-
|
72
|
-
|
89
|
+
@current_session.select_resolver(resolver, @current_selector)
|
90
|
+
end
|
73
91
|
end
|
74
92
|
end
|
75
93
|
end
|