lib/httpx/resolver/https.rb in httpx-0.22.5 vs lib/httpx/resolver/https.rb in httpx-0.23.0
- old
+ new
@@ -102,20 +102,20 @@
request.on(:promise, &method(:on_promise))
@requests[request] = hostname
resolver_connection.send(request)
@connections << connection
rescue ResolveError, Resolv::DNS::EncodeError => e
- @queries.delete(hostname)
+ reset_hostname(hostname)
emit_resolve_error(connection, connection.origin.host, e)
end
end
def on_response(request, response)
response.raise_for_status
rescue StandardError => e
hostname = @requests.delete(request)
- connection = @queries.delete(hostname)
+ connection = reset_hostname(hostname)
emit_resolve_error(connection, connection.origin.host, e)
else
# @type var response: HTTPX::Response
parse(request, response)
ensure
@@ -126,45 +126,50 @@
log(level: 2) { "#{stream.id}: refusing stream!" }
stream.refuse
end
def parse(request, response)
- begin
- answers = decode_response_body(response)
- rescue Resolv::DNS::DecodeError => e
- host, connection = @queries.first
- @queries.delete(host)
- emit_resolve_error(connection, connection.origin.host, e)
- return
- end
+ code, result = decode_response_body(response)
- if answers.nil?
+ case code
+ when :ok
+ parse_addresses(result)
+ when :no_domain_found
# Indicates no such domain was found.
host = @requests.delete(request)
- connection = @queries.delete(host)
+ connection = reset_hostname(host)
- emit_resolve_error(connection) unless @queries.value?(connection)
- elsif answers.empty?
- # no address found, eliminate candidates
+ emit_resolve_error(connection)
+ when :dns_error
host = @requests.delete(request)
- connection = @queries.delete(host)
+ connection = reset_hostname(host)
- # eliminate other candidates
- @queries.delete_if { |_, conn| connection == conn }
+ emit_resolve_error(connection)
+ when :decode_error
+ host, connection = @queries.first
+ reset_hostname(host)
+ emit_resolve_error(connection, connection.origin.host, result)
+ end
+ end
+ def parse_addresses(answers)
+ if answers.empty?
+ # no address found, eliminate candidates
+ host = @requests.delete(request)
+ connection = reset_hostname(host)
emit_resolve_error(connection)
return
else
answers = answers.group_by { |answer| answer["name"] }
answers.each do |hostname, addresses|
addresses = addresses.flat_map do |address|
if address.key?("alias")
alias_address = answers[address["alias"]]
if alias_address.nil?
- @queries.delete(address["name"])
+ reset_hostname(address["name"])
if catch(:coalesced) { early_resolve(connection, hostname: address["alias"]) }
@connections.delete(connection)
else
resolve(connection, address["alias"])
return # rubocop:disable Lint/NonLocalExitFromIterator
@@ -177,11 +182,11 @@
end
end.compact
next if addresses.empty?
hostname.delete_suffix!(".") if hostname.end_with?(".")
- connection = @queries.delete(hostname)
+ connection = reset_hostname(hostname, reset_candidates: false)
next unless connection # probably a retried query for which there's an answer
@connections.delete(connection)
# eliminate other candidates
@@ -221,8 +226,20 @@
"application/dns-message"
Resolver.decode_dns_answer(response.to_s)
else
raise Error, "unsupported DNS mime-type (#{response.headers["content-type"]})"
end
+ end
+
+ def reset_hostname(hostname, reset_candidates: true)
+ connection = @queries.delete(hostname)
+
+ return connection unless connection && reset_candidates
+
+ # eliminate other candidates
+ candidates = @queries.select { |_, conn| connection == conn }.keys
+ @queries.delete_if { |h, _| candidates.include?(h) }
+
+ connection
end
end
end