httpx 0.9.0 → 0.10.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/LICENSE.txt +48 -0
- data/README.md +2 -0
- data/doc/release_notes/0_10_0.md +66 -0
- data/lib/httpx.rb +2 -0
- data/lib/httpx/adapters/faraday.rb +1 -1
- data/lib/httpx/chainable.rb +2 -2
- data/lib/httpx/connection.rb +3 -9
- data/lib/httpx/connection/http1.rb +1 -1
- data/lib/httpx/domain_name.rb +440 -0
- data/lib/httpx/errors.rb +1 -0
- data/lib/httpx/extensions.rb +21 -1
- data/lib/httpx/io/ssl.rb +0 -1
- data/lib/httpx/io/tcp.rb +6 -5
- data/lib/httpx/io/udp.rb +4 -1
- data/lib/httpx/options.rb +2 -0
- data/lib/httpx/parser/http1.rb +14 -17
- data/lib/httpx/plugins/compression.rb +28 -63
- data/lib/httpx/plugins/compression/brotli.rb +10 -14
- data/lib/httpx/plugins/compression/deflate.rb +7 -6
- data/lib/httpx/plugins/compression/gzip.rb +23 -5
- data/lib/httpx/plugins/cookies.rb +21 -60
- data/lib/httpx/plugins/cookies/cookie.rb +173 -0
- data/lib/httpx/plugins/cookies/jar.rb +74 -0
- data/lib/httpx/plugins/cookies/set_cookie_parser.rb +142 -0
- data/lib/httpx/plugins/expect.rb +3 -5
- data/lib/httpx/plugins/follow_redirects.rb +20 -2
- data/lib/httpx/plugins/h2c.rb +1 -1
- data/lib/httpx/plugins/multipart.rb +0 -8
- data/lib/httpx/plugins/persistent.rb +6 -1
- data/lib/httpx/plugins/proxy/socks4.rb +3 -1
- data/lib/httpx/plugins/rate_limiter.rb +51 -0
- data/lib/httpx/plugins/retries.rb +3 -2
- data/lib/httpx/plugins/stream.rb +109 -13
- data/lib/httpx/pool.rb +6 -6
- data/lib/httpx/request.rb +7 -19
- data/lib/httpx/resolver/https.rb +7 -2
- data/lib/httpx/resolver/native.rb +7 -3
- data/lib/httpx/response.rb +16 -23
- data/lib/httpx/selector.rb +2 -4
- data/lib/httpx/session.rb +17 -11
- data/lib/httpx/transcoder/chunker.rb +0 -2
- data/lib/httpx/transcoder/form.rb +0 -6
- data/lib/httpx/transcoder/json.rb +0 -4
- data/lib/httpx/utils.rb +45 -0
- data/lib/httpx/version.rb +1 -1
- data/sig/buffer.rbs +24 -0
- data/sig/callbacks.rbs +14 -0
- data/sig/chainable.rbs +37 -0
- data/sig/connection.rbs +2 -0
- data/sig/connection/http2.rbs +4 -0
- data/sig/domain_name.rbs +17 -0
- data/sig/errors.rbs +3 -0
- data/sig/headers.rbs +42 -0
- data/sig/httpx.rbs +14 -0
- data/sig/loggable.rbs +11 -0
- data/sig/missing.rbs +12 -0
- data/sig/options.rbs +118 -0
- data/sig/parser/http1.rbs +50 -0
- data/sig/plugins/authentication.rbs +11 -0
- data/sig/plugins/basic_authentication.rbs +13 -0
- data/sig/plugins/compression.rbs +55 -0
- data/sig/plugins/compression/brotli.rbs +21 -0
- data/sig/plugins/compression/deflate.rbs +17 -0
- data/sig/plugins/compression/gzip.rbs +29 -0
- data/sig/plugins/cookies.rbs +26 -0
- data/sig/plugins/cookies/cookie.rbs +50 -0
- data/sig/plugins/cookies/jar.rbs +27 -0
- data/sig/plugins/digest_authentication.rbs +33 -0
- data/sig/plugins/expect.rbs +19 -0
- data/sig/plugins/follow_redirects.rbs +37 -0
- data/sig/plugins/h2c.rbs +26 -0
- data/sig/plugins/multipart.rbs +19 -0
- data/sig/plugins/persistent.rbs +17 -0
- data/sig/plugins/proxy.rbs +47 -0
- data/sig/plugins/proxy/http.rbs +14 -0
- data/sig/plugins/proxy/socks4.rbs +33 -0
- data/sig/plugins/proxy/socks5.rbs +36 -0
- data/sig/plugins/proxy/ssh.rbs +18 -0
- data/sig/plugins/push_promise.rbs +22 -0
- data/sig/plugins/rate_limiter.rbs +11 -0
- data/sig/plugins/retries.rbs +48 -0
- data/sig/plugins/stream.rbs +39 -0
- data/sig/pool.rbs +2 -0
- data/sig/registry.rbs +9 -0
- data/sig/request.rbs +61 -0
- data/sig/response.rbs +87 -0
- data/sig/session.rbs +49 -0
- data/sig/test.rbs +9 -0
- data/sig/timeout.rbs +29 -0
- data/sig/transcoder.rbs +16 -0
- data/sig/transcoder/body.rbs +18 -0
- data/sig/transcoder/chunker.rbs +32 -0
- data/sig/transcoder/form.rbs +16 -0
- data/sig/transcoder/json.rbs +14 -0
- metadata +60 -17
data/lib/httpx/plugins/expect.rb
CHANGED
@@ -33,11 +33,8 @@ module HTTPX
|
|
33
33
|
super
|
34
34
|
return if @body.nil?
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
return if @body.bytesize < threshold
|
39
|
-
end
|
40
|
-
end
|
36
|
+
threshold = options.expect_threshold_size
|
37
|
+
return if threshold && !unbounded_body? && @body.bytesize < threshold
|
41
38
|
|
42
39
|
@headers["expect"] = "100-continue"
|
43
40
|
end
|
@@ -63,6 +60,7 @@ module HTTPX
|
|
63
60
|
return unless response
|
64
61
|
|
65
62
|
if response.status == 417 && request.headers.key?("expect")
|
63
|
+
response.close
|
66
64
|
request.headers.delete("expect")
|
67
65
|
request.transition(:idle)
|
68
66
|
connection = find_connection(request, connections, options)
|
@@ -59,8 +59,26 @@ module HTTPX
|
|
59
59
|
return ErrorResponse.new(request, error, options)
|
60
60
|
end
|
61
61
|
|
62
|
-
|
63
|
-
|
62
|
+
retry_after = response.headers["retry-after"]
|
63
|
+
|
64
|
+
if retry_after
|
65
|
+
# Servers send the "Retry-After" header field to indicate how long the
|
66
|
+
# user agent ought to wait before making a follow-up request.
|
67
|
+
# When sent with any 3xx (Redirection) response, Retry-After indicates
|
68
|
+
# the minimum time that the user agent is asked to wait before issuing
|
69
|
+
# the redirected request.
|
70
|
+
#
|
71
|
+
retry_after = Utils.parse_retry_after(retry_after)
|
72
|
+
|
73
|
+
log { "redirecting after #{retry_after} secs..." }
|
74
|
+
pool.after(retry_after) do
|
75
|
+
connection = find_connection(retry_request, connections, options)
|
76
|
+
connection.send(retry_request)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
connection = find_connection(retry_request, connections, options)
|
80
|
+
connection.send(retry_request)
|
81
|
+
end
|
64
82
|
nil
|
65
83
|
end
|
66
84
|
|
data/lib/httpx/plugins/h2c.rb
CHANGED
@@ -19,7 +19,12 @@ module HTTPX
|
|
19
19
|
#
|
20
20
|
module Persistent
|
21
21
|
def self.load_dependencies(klass)
|
22
|
-
klass.
|
22
|
+
max_retries = if klass.default_options.respond_to?(:max_retries)
|
23
|
+
[klass.default_options.max_retries, 1].max
|
24
|
+
else
|
25
|
+
1
|
26
|
+
end
|
27
|
+
klass.plugin(:retries, max_retries: max_retries, retry_change_requests: true)
|
23
28
|
end
|
24
29
|
|
25
30
|
def self.extra_options(options)
|
@@ -91,6 +91,8 @@ module HTTPX
|
|
91
91
|
end
|
92
92
|
|
93
93
|
module Packet
|
94
|
+
using(RegexpExtensions) unless Regexp.method_defined?(:match?)
|
95
|
+
|
94
96
|
module_function
|
95
97
|
|
96
98
|
def connect(parameters, uri)
|
@@ -101,7 +103,7 @@ module HTTPX
|
|
101
103
|
|
102
104
|
packet << [ip.to_i].pack("N")
|
103
105
|
rescue IPAddr::InvalidAddressError
|
104
|
-
if parameters.uri.scheme
|
106
|
+
if /^socks4a?$/.match?(parameters.uri.scheme)
|
105
107
|
# resolv defaults to IPv4, and socks4 doesn't support IPv6 otherwise
|
106
108
|
ip = IPAddr.new(Resolv.getaddress(uri.host))
|
107
109
|
packet << [ip.to_i].pack("N")
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTPX
|
4
|
+
module Plugins
|
5
|
+
#
|
6
|
+
# This plugin adds support for retrying requests when the request:
|
7
|
+
#
|
8
|
+
# * is rate limited;
|
9
|
+
# * when the server is unavailable (503);
|
10
|
+
# * when a 3xx request comes with a "retry-after" value
|
11
|
+
#
|
12
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/RateLimiter
|
13
|
+
#
|
14
|
+
module RateLimiter
|
15
|
+
class << self
|
16
|
+
RATE_LIMIT_CODES = [429, 503].freeze
|
17
|
+
|
18
|
+
def load_dependencies(klass)
|
19
|
+
klass.plugin(:retries,
|
20
|
+
retry_change_requests: true,
|
21
|
+
retry_on: method(:retry_on_rate_limited_response),
|
22
|
+
retry_after: method(:retry_after_rate_limit))
|
23
|
+
end
|
24
|
+
|
25
|
+
def retry_on_rate_limited_response(response)
|
26
|
+
status = response.status
|
27
|
+
|
28
|
+
RATE_LIMIT_CODES.include?(status)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Servers send the "Retry-After" header field to indicate how long the
|
32
|
+
# user agent ought to wait before making a follow-up request. When
|
33
|
+
# sent with a 503 (Service Unavailable) response, Retry-After indicates
|
34
|
+
# how long the service is expected to be unavailable to the client.
|
35
|
+
# When sent with any 3xx (Redirection) response, Retry-After indicates
|
36
|
+
# the minimum time that the user agent is asked to wait before issuing
|
37
|
+
# the redirected request.
|
38
|
+
#
|
39
|
+
def retry_after_rate_limit(_, response)
|
40
|
+
retry_after = response.headers["retry-after"]
|
41
|
+
|
42
|
+
return unless retry_after
|
43
|
+
|
44
|
+
Utils.parse_retry_after(retry_after)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
register_plugin :rate_limiter, RateLimiter
|
50
|
+
end
|
51
|
+
end
|
@@ -75,14 +75,15 @@ module HTTPX
|
|
75
75
|
)
|
76
76
|
# rubocop:enable Style/MultilineTernaryOperator
|
77
77
|
)
|
78
|
-
|
78
|
+
response.close if response.respond_to?(:close)
|
79
79
|
request.retries -= 1
|
80
80
|
log { "failed to get response, #{request.retries} tries to go..." }
|
81
81
|
request.transition(:idle)
|
82
82
|
|
83
83
|
retry_after = options.retry_after
|
84
|
+
retry_after = retry_after.call(request, response) if retry_after.respond_to?(:call)
|
85
|
+
|
84
86
|
if retry_after
|
85
|
-
retry_after = retry_after.call(request) if retry_after.respond_to?(:call)
|
86
87
|
|
87
88
|
log { "retrying after #{retry_after} secs..." }
|
88
89
|
pool.after(retry_after) do
|
data/lib/httpx/plugins/stream.rb
CHANGED
@@ -7,27 +7,123 @@ module HTTPX
|
|
7
7
|
#
|
8
8
|
module Stream
|
9
9
|
module InstanceMethods
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
private
|
11
|
+
|
12
|
+
def request(*args, stream: false, **options)
|
13
|
+
return super(*args, **options) unless stream
|
14
|
+
|
15
|
+
requests = args.first.is_a?(Request) ? args : build_requests(*args, options)
|
16
|
+
|
17
|
+
raise Error, "only 1 response at a time is supported for streaming requests" unless requests.size == 1
|
18
|
+
|
19
|
+
StreamResponse.new(requests.first, self)
|
13
20
|
end
|
14
21
|
end
|
15
22
|
|
23
|
+
module RequestMethods
|
24
|
+
attr_accessor :stream
|
25
|
+
end
|
26
|
+
|
16
27
|
module ResponseMethods
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
28
|
+
def stream
|
29
|
+
@request.stream
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module ResponseBodyMethods
|
34
|
+
def initialize(*, **)
|
35
|
+
super
|
36
|
+
@stream = @response.stream
|
37
|
+
end
|
38
|
+
|
39
|
+
def write(chunk)
|
40
|
+
return super unless @stream
|
41
|
+
|
42
|
+
@stream.on_chunk(chunk.to_s.dup)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def transition(*)
|
48
|
+
return if @stream
|
49
|
+
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class StreamResponse
|
55
|
+
def initialize(request, session)
|
56
|
+
@request = request
|
57
|
+
@session = session
|
58
|
+
@options = @request.options
|
59
|
+
end
|
60
|
+
|
61
|
+
def each(&block)
|
62
|
+
return enum_for(__method__) unless block_given?
|
63
|
+
|
64
|
+
raise Error, "response already streamed" if @response
|
65
|
+
|
66
|
+
@request.stream = self
|
67
|
+
|
68
|
+
begin
|
69
|
+
@on_chunk = block
|
70
|
+
|
71
|
+
response.raise_for_status
|
72
|
+
response.close
|
73
|
+
ensure
|
74
|
+
@on_chunk = nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def each_line
|
79
|
+
return enum_for(__method__) unless block_given?
|
80
|
+
|
81
|
+
line = +""
|
82
|
+
|
83
|
+
each do |chunk|
|
84
|
+
line << chunk
|
85
|
+
|
86
|
+
while (idx = line.index("\n"))
|
87
|
+
yield line.byteslice(0..idx - 1)
|
88
|
+
|
89
|
+
line = line.byteslice(idx + 1..-1)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# This is a ghost method. It's to be used ONLY internally, when processing streams
|
95
|
+
def on_chunk(chunk)
|
96
|
+
raise NoMethodError unless @on_chunk
|
97
|
+
|
98
|
+
@on_chunk.call(chunk)
|
99
|
+
end
|
100
|
+
|
101
|
+
# :nocov:
|
102
|
+
def inspect
|
103
|
+
"#<StreamResponse:#{object_id}>"
|
104
|
+
end
|
105
|
+
# :nocov:
|
106
|
+
|
107
|
+
def to_s
|
108
|
+
response.to_s
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def response
|
114
|
+
@response ||= @session.__send__(:send_requests, @request, @options).first
|
21
115
|
end
|
22
116
|
|
23
|
-
def
|
24
|
-
@
|
117
|
+
def respond_to_missing?(*args)
|
118
|
+
@options.response_class.respond_to?(*args) || super
|
25
119
|
end
|
26
120
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
121
|
+
def method_missing(meth, *args, &block)
|
122
|
+
if @options.response_class.public_method_defined?(meth)
|
123
|
+
response.__send__(meth, *args, &block)
|
124
|
+
else
|
125
|
+
super
|
126
|
+
end
|
31
127
|
end
|
32
128
|
end
|
33
129
|
end
|
data/lib/httpx/pool.rb
CHANGED
@@ -37,20 +37,22 @@ module HTTPX
|
|
37
37
|
|
38
38
|
@timers.fire
|
39
39
|
end
|
40
|
-
rescue Interrupt
|
41
|
-
@connections.each(&:reset)
|
42
|
-
raise
|
43
40
|
rescue StandardError => e
|
44
41
|
@connections.each do |connection|
|
45
42
|
connection.emit(:error, e)
|
46
43
|
end
|
44
|
+
rescue Exception # rubocop:disable Lint/RescueException
|
45
|
+
@connections.each(&:reset)
|
46
|
+
raise
|
47
47
|
end
|
48
48
|
|
49
49
|
def close(connections = @connections)
|
50
|
+
return if connections.empty?
|
51
|
+
|
50
52
|
@timers.cancel
|
51
53
|
connections = connections.reject(&:inflight?)
|
52
54
|
connections.each(&:close)
|
53
|
-
next_tick until connections.none? { |c| @connections.include?(c) }
|
55
|
+
next_tick until connections.none? { |c| c.state != :idle && @connections.include?(c) }
|
54
56
|
@resolvers.each_value do |resolver|
|
55
57
|
resolver.close unless resolver.closed?
|
56
58
|
end if @connections.empty?
|
@@ -166,7 +168,6 @@ module HTTPX
|
|
166
168
|
resolver.on(:error, &method(:on_resolver_error))
|
167
169
|
resolver.on(:close) { on_resolver_close(resolver) }
|
168
170
|
resolver
|
169
|
-
# rubocop: disable Layout/RescueEnsureAlignment
|
170
171
|
rescue ArgumentError
|
171
172
|
# this block is here because of an error which happens on CI from time to time
|
172
173
|
warn "tried resolver: #{resolver_type}"
|
@@ -174,7 +175,6 @@ module HTTPX
|
|
174
175
|
warn "new: #{resolver_type.method(:new).source_location}"
|
175
176
|
raise
|
176
177
|
end
|
177
|
-
# rubocop: enable Layout/RescueEnsureAlignment
|
178
178
|
end
|
179
179
|
end
|
180
180
|
end
|
data/lib/httpx/request.rb
CHANGED
@@ -33,11 +33,7 @@ module HTTPX
|
|
33
33
|
|
34
34
|
USER_AGENT = "httpx.rb/#{VERSION}"
|
35
35
|
|
36
|
-
attr_reader :verb, :uri, :headers, :body, :state
|
37
|
-
|
38
|
-
attr_reader :options, :response
|
39
|
-
|
40
|
-
def_delegator :@body, :<<
|
36
|
+
attr_reader :verb, :uri, :headers, :body, :state, :options, :response
|
41
37
|
|
42
38
|
def_delegator :@body, :empty?
|
43
39
|
|
@@ -45,7 +41,7 @@ module HTTPX
|
|
45
41
|
|
46
42
|
def initialize(verb, uri, options = {})
|
47
43
|
@verb = verb.to_s.downcase.to_sym
|
48
|
-
@uri =
|
44
|
+
@uri = Utils.uri(uri)
|
49
45
|
@options = Options.new(options)
|
50
46
|
|
51
47
|
raise(Error, "unknown method: #{verb}") unless METHODS.include?(@verb)
|
@@ -64,17 +60,15 @@ module HTTPX
|
|
64
60
|
:w
|
65
61
|
end
|
66
62
|
|
67
|
-
# :nocov:
|
68
63
|
if RUBY_VERSION < "2.2"
|
69
|
-
|
64
|
+
URIParser = URI::DEFAULT_PARSER
|
65
|
+
|
70
66
|
def initialize_with_escape(verb, uri, options = {})
|
71
|
-
initialize_without_escape(verb,
|
67
|
+
initialize_without_escape(verb, URIParser.escape(uri.to_s), options)
|
72
68
|
end
|
73
69
|
alias_method :initialize_without_escape, :initialize
|
74
70
|
alias_method :initialize, :initialize_with_escape
|
75
|
-
# rubocop: enable Lint/UriEscapeUnescape:
|
76
71
|
end
|
77
|
-
# :nocov:
|
78
72
|
|
79
73
|
def merge_headers(h)
|
80
74
|
@headers = @headers.merge(h)
|
@@ -180,19 +174,13 @@ module HTTPX
|
|
180
174
|
return true if @body.nil?
|
181
175
|
return false if chunked?
|
182
176
|
|
183
|
-
bytesize.zero?
|
177
|
+
@body.bytesize.zero?
|
184
178
|
end
|
185
179
|
|
186
180
|
def bytesize
|
187
181
|
return 0 if @body.nil?
|
188
182
|
|
189
|
-
|
190
|
-
@body.bytesize
|
191
|
-
elsif @body.respond_to?(:size)
|
192
|
-
@body.size
|
193
|
-
else
|
194
|
-
raise Error, "cannot determine size of body: #{@body.inspect}"
|
195
|
-
end
|
183
|
+
@body.bytesize
|
196
184
|
end
|
197
185
|
|
198
186
|
def stream(body)
|
data/lib/httpx/resolver/https.rb
CHANGED
@@ -94,7 +94,12 @@ module HTTPX
|
|
94
94
|
def resolve(connection = @connections.first, hostname = nil)
|
95
95
|
return if @building_connection
|
96
96
|
|
97
|
-
hostname
|
97
|
+
hostname ||= @queries.key(connection)
|
98
|
+
|
99
|
+
if hostname.nil?
|
100
|
+
hostname = connection.origin.host
|
101
|
+
log { "resolver: resolve IDN #{connection.origin.non_ascii_hostname} as #{hostname}" } if connection.origin.non_ascii_hostname
|
102
|
+
end
|
98
103
|
type = @_record_types[hostname].first
|
99
104
|
log { "resolver: query #{type} for #{hostname}" }
|
100
105
|
begin
|
@@ -206,7 +211,7 @@ module HTTPX
|
|
206
211
|
case response.headers["content-type"]
|
207
212
|
when "application/dns-json",
|
208
213
|
"application/json",
|
209
|
-
%r{^application
|
214
|
+
%r{^application/x-javascript} # because google...
|
210
215
|
payload = JSON.parse(response.to_s)
|
211
216
|
payload["Answer"]
|
212
217
|
when "application/dns-udpwireformat",
|
@@ -7,6 +7,7 @@ module HTTPX
|
|
7
7
|
class Resolver::Native
|
8
8
|
extend Forwardable
|
9
9
|
include Resolver::ResolverMixin
|
10
|
+
using URIExtensions
|
10
11
|
|
11
12
|
RESOLVE_TIMEOUT = 5
|
12
13
|
RECORD_TYPES = {
|
@@ -168,7 +169,6 @@ module HTTPX
|
|
168
169
|
siz = @io.read(wsize, @read_buffer)
|
169
170
|
return unless siz && siz.positive?
|
170
171
|
|
171
|
-
log { "resolver: READ: #{siz} bytes..." }
|
172
172
|
parse(@read_buffer)
|
173
173
|
return if @state == :closed
|
174
174
|
end
|
@@ -181,7 +181,6 @@ module HTTPX
|
|
181
181
|
siz = @io.write(@write_buffer)
|
182
182
|
return unless siz && siz.positive?
|
183
183
|
|
184
|
-
log { "resolver: WRITE: #{siz} bytes..." }
|
185
184
|
return if @state == :closed
|
186
185
|
end
|
187
186
|
end
|
@@ -237,7 +236,12 @@ module HTTPX
|
|
237
236
|
raise Error, "no URI to resolve" unless connection
|
238
237
|
return unless @write_buffer.empty?
|
239
238
|
|
240
|
-
hostname
|
239
|
+
hostname ||= @queries.key(connection)
|
240
|
+
|
241
|
+
if hostname.nil?
|
242
|
+
hostname = connection.origin.host
|
243
|
+
log { "resolver: resolve IDN #{connection.origin.non_ascii_hostname} as #{hostname}" } if connection.origin.non_ascii_hostname
|
244
|
+
end
|
241
245
|
@queries[hostname] = connection
|
242
246
|
type = @_record_types[hostname].first
|
243
247
|
log { "resolver: query #{type} for #{hostname}" }
|