lib/httpx/resolver/native.rb in httpx-1.2.4 vs lib/httpx/resolver/native.rb in httpx-1.2.6
- old
+ new
@@ -63,10 +63,11 @@
@ns_index += 1
nameserver = @nameserver
if nameserver && @ns_index < nameserver.size
log { "resolver: failed resolving on nameserver #{@nameserver[@ns_index - 1]} (#{e.message})" }
transition(:idle)
+ @timeouts.clear
else
handle_error(e)
end
rescue NativeResolveError => e
handle_error(e)
@@ -141,17 +142,20 @@
@timeouts[host].shift
if !@timeouts[host].empty?
log { "resolver: timeout after #{timeout}s, retry(#{@timeouts[host].first}) #{host}..." }
- resolve(connection)
+ # must downgrade to tcp AND retry on same host as last
+ downgrade_socket
+ resolve(connection, h)
elsif @ns_index + 1 < @nameserver.size
# try on the next nameserver
@ns_index += 1
log { "resolver: failed resolving #{host} on nameserver #{@nameserver[@ns_index - 1]} (timeout error)" }
transition(:idle)
- resolve(connection)
+ @timeouts.clear
+ resolve(connection, h)
else
@timeouts.delete(host)
reset_hostname(h, reset_candidates: false)
@@ -185,14 +189,13 @@
@large_packet << @read_buffer
next unless @large_packet.full?
parse(@large_packet.to_s)
- @socket_type = @resolver_options.fetch(:socket_type, :udp)
@large_packet = nil
- transition(:idle)
- transition(:open)
+ # downgrade to udp again
+ downgrade_socket
return
else
size = @read_buffer[0, 2].unpack1("n")
buffer = @read_buffer.byteslice(2..-1)
@@ -302,17 +305,25 @@
address["name"] = name
connection = @queries.delete(name)
end
if address.key?("alias") # CNAME
+ hostname_alias = address["alias"]
# clean up intermediate queries
@timeouts.delete(name) unless connection.origin.host == name
- if catch(:coalesced) { early_resolve(connection, hostname: address["alias"]) }
+ if catch(:coalesced) { early_resolve(connection, hostname: hostname_alias) }
@connections.delete(connection)
else
- resolve(connection, address["alias"])
+ if @socket_type == :tcp
+ # must downgrade to udp if tcp
+ @socket_type = @resolver_options.fetch(:socket_type, :udp)
+ transition(:idle)
+ transition(:open)
+ end
+ log { "resolver: ALIAS #{hostname_alias} for #{name}" }
+ resolve(connection, hostname_alias)
return
end
else
reset_hostname(name, connection: connection)
@timeouts.delete(connection.origin.host)
@@ -384,17 +395,24 @@
origin = URI("tcp://#{ip}:#{port}")
TCP.new(origin, [ip], @options)
end
end
+ def downgrade_socket
+ return unless @socket_type == :tcp
+
+ @socket_type = @resolver_options.fetch(:socket_type, :udp)
+ transition(:idle)
+ transition(:open)
+ end
+
def transition(nextstate)
case nextstate
when :idle
if @io
@io.close
@io = nil
end
- @timeouts.clear
when :open
return unless @state == :idle
@io ||= build_socket