lib/httpx/resolver/native.rb in httpx-0.18.7 vs lib/httpx/resolver/native.rb in httpx-0.19.0

- old
+ new

@@ -2,34 +2,26 @@ require "forwardable" require "resolv" module HTTPX - class Resolver::Native + class Resolver::Native < Resolver::Resolver extend Forwardable - include Resolver::ResolverMixin using URIExtensions - RECORD_TYPES = { - "A" => Resolv::DNS::Resource::IN::A, - "AAAA" => Resolv::DNS::Resource::IN::AAAA, - }.freeze - DEFAULTS = if RUBY_VERSION < "2.2" { **Resolv::DNS::Config.default_config_hash, packet_size: 512, timeouts: Resolver::RESOLVE_TIMEOUT, - record_types: RECORD_TYPES.keys, }.freeze else { nameserver: nil, **Resolv::DNS::Config.default_config_hash, packet_size: 512, timeouts: Resolver::RESOLVE_TIMEOUT, - record_types: RECORD_TYPES.keys, }.freeze end # nameservers for ipv6 are misconfigured in certain systems; # this can use an unexpected endless loop @@ -47,18 +39,17 @@ def_delegator :@connections, :empty? attr_reader :state - def initialize(options) - @options = HTTPX::Options.new(options) + def initialize(_, options) + super @ns_index = 0 @resolver_options = DEFAULTS.merge(@options.resolver_options) @nameserver = @resolver_options[:nameserver] @_timeouts = Array(@resolver_options[:timeouts]) @timeouts = Hash.new { |timeouts, host| timeouts[host] = @_timeouts.dup } - @_record_types = Hash.new { |types, host| types[host] = @resolver_options[:record_types].dup } @connections = [] @queries = {} @read_buffer = "".b @write_buffer = Buffer.new(@resolver_options[:packet_size]) @state = :idle @@ -105,12 +96,10 @@ calculate_interests end def <<(connection) - return if early_resolve(connection) - if @nameserver.nil? ex = ResolveError.new("No available nameserver") ex.set_backtrace(caller) throw(:resolve_error, ex) else @@ -138,11 +127,11 @@ do_retry dwrite if calculate_interests == :w end def do_retry - return if @queries.empty? + return if @queries.empty? || !@start_timeout loop_time = Utils.elapsed_time(@start_timeout) connections = [] queries = {} while (query = @queries.shift) @@ -158,11 +147,11 @@ if @timeouts[host].empty? @timeouts.delete(host) @connections.delete(connection) # This loop_time passed to the exception is bogus. Ideally we would pass the total # resolve timeout, including from the previous retries. - raise ResolveTimeoutError.new(loop_time, "Timed out") + raise ResolveTimeoutError.new(loop_time, "Timed out while resolving #{host}") # raise NativeResolveError.new(connection, host) else log { "resolver: timeout after #{timeout}s, retry(#{@timeouts[host].first}) #{host}..." } connections << connection queries[h] = connection @@ -196,31 +185,25 @@ def parse(buffer) begin addresses = Resolver.decode_dns_answer(buffer) rescue Resolv::DNS::DecodeError => e hostname, connection = @queries.first - if @_record_types[hostname].empty? - @queries.delete(hostname) - @timeouts.delete(hostname) - @connections.delete(connection) - ex = NativeResolveError.new(connection, hostname, e.message) - ex.set_backtrace(e.backtrace) - raise ex - end + @queries.delete(hostname) + @timeouts.delete(hostname) + @connections.delete(connection) + ex = NativeResolveError.new(connection, hostname, e.message) + ex.set_backtrace(e.backtrace) + raise ex end if addresses.nil? || addresses.empty? hostname, connection = @queries.first - @_record_types[hostname].shift - if @_record_types[hostname].empty? - @queries.delete(hostname) - @_record_types.delete(hostname) - @timeouts.delete(hostname) - @connections.delete(connection) + @queries.delete(hostname) + @timeouts.delete(hostname) + @connections.delete(connection) - raise NativeResolveError.new(connection, hostname) - end + raise NativeResolveError.new(connection, hostname) else address = addresses.first name = address["name"] connection = @queries.delete(name) @@ -237,24 +220,24 @@ connection = @queries.delete(name) end if address.key?("alias") # CNAME # clean up intermediate queries - @timeouts.delete(address["name"]) unless connection.origin.host == address["name"] + @timeouts.delete(name) unless connection.origin.host == name if catch(:coalesced) { early_resolve(connection, hostname: address["alias"]) } - @timeouts.delete(connection.origin.host) @connections.delete(connection) else resolve(connection, address["alias"]) return end else + @timeouts.delete(name) @timeouts.delete(connection.origin.host) @connections.delete(connection) - Resolver.cached_lookup_set(connection.origin.host, addresses) if @resolver_options[:cache] - emit_addresses(connection, addresses.map { |addr| addr["data"] }) + Resolver.cached_lookup_set(connection.origin.host, @family, addresses) if @resolver_options[:cache] + emit_addresses(connection, @family, addresses.map { |addr| addr["data"] }) end end return emit(:close) if @connections.empty? resolve @@ -269,14 +252,13 @@ if hostname.nil? hostname = connection.origin.host log { "resolver: resolve IDN #{connection.origin.non_ascii_hostname} as #{hostname}" } if connection.origin.non_ascii_hostname end @queries[hostname] = connection - type = @_record_types[hostname].first || "A" - log { "resolver: query #{type} for #{hostname}" } + log { "resolver: query #{@record_type.name.split("::").last} for #{hostname}" } begin - @write_buffer << Resolver.encode_dns_query(hostname, type: RECORD_TYPES[type]) + @write_buffer << Resolver.encode_dns_query(hostname, type: @record_type) rescue Resolv::DNS::EncodeError => e emit_resolve_error(connection, hostname, e) end end @@ -311,9 +293,12 @@ resolve if @queries.empty? && !@connections.empty? when :closed return unless @state == :open @io.close if @io + @start_timeout = nil + @write_buffer.clear + @read_buffer.clear end @state = nextstate end def handle_error(error)