class HTTPX::Resolver::Resolver

  1. lib/httpx/resolver/resolver.rb
Superclass: Object

Base class for all internal internet name resolvers. It handles basic blocks from the Selectable API.

Included modules

  1. Loggable

Constants

FAMILY_TYPES = { Resolv::DNS::Resource::IN::AAAA => "AAAA", Resolv::DNS::Resource::IN::A => "A", }.freeze  
RECORD_TYPES = { Socket::AF_INET6 => Resolv::DNS::Resource::IN::AAAA, Socket::AF_INET => Resolv::DNS::Resource::IN::A, }.freeze  

Public Instance Aliases

terminate -> close

Attributes

Public Class methods

multi?()
[show source]
   # File lib/httpx/resolver/resolver.rb
25 def multi?
26   true
27 end
new(family, options)
[show source]
   # File lib/httpx/resolver/resolver.rb
36 def initialize(family, options)
37   @family = family
38   @record_type = RECORD_TYPES[family]
39   @options = options
40   @connections = []
41 end

Public Instance methods

close()
[show source]
   # File lib/httpx/resolver/resolver.rb
51 def close; end
closed?()
[show source]
   # File lib/httpx/resolver/resolver.rb
65 def closed?
66   true
67 end
each_connection(&block)
[show source]
   # File lib/httpx/resolver/resolver.rb
43 def each_connection(&block)
44   enum_for(__method__) unless block
45 
46   return unless @connections
47 
48   @connections.each(&block)
49 end
early_resolve(connection, hostname: connection.peer.host)
[show source]
    # File lib/httpx/resolver/resolver.rb
136 def early_resolve(connection, hostname: connection.peer.host) # rubocop:disable Naming/PredicateMethod
137   addresses = @resolver_options[:cache] && (connection.addresses || @options.resolver_cache.resolve(hostname))
138 
139   return false unless addresses
140 
141   addresses = addresses.select { |addr| addr.family == @family }
142 
143   return false if addresses.empty?
144 
145   emit_addresses(connection, @family, addresses, true)
146 
147   true
148 end
emit_addresses(connection, family, addresses, early_resolve = false)
[show source]
    # File lib/httpx/resolver/resolver.rb
 77 def emit_addresses(connection, family, addresses, early_resolve = false)
 78   addresses.map! { |address| address.is_a?(Resolver::Entry) ? address : Resolver::Entry.new(address) }
 79 
 80   # double emission check, but allow early resolution to work
 81   conn_addrs = connection.addresses
 82   return if !early_resolve && conn_addrs && !conn_addrs.empty? && !addresses.intersect?(conn_addrs)
 83 
 84   log do
 85     "resolver #{FAMILY_TYPES[RECORD_TYPES[family]]}: " \
 86       "answer #{connection.peer.host}: #{addresses.inspect} (early resolve: #{early_resolve})"
 87   end
 88 
 89   # do not apply resolution delay for non-dns name resolution
 90   if !early_resolve &&
 91      # just in case...
 92      @current_selector &&
 93      # resolution delay only applies to IPv4
 94      family == Socket::AF_INET &&
 95      # connection already has addresses and initiated/ended handshake
 96      !connection.io &&
 97      # no need to delay if not supporting dual stack / multi-homed IP
 98      (connection.options.ip_families || Resolver.supported_ip_families).size > 1 &&
 99      # connection URL host is already the IP (early resolve included perhaps?)
100      addresses.first.to_s != connection.peer.host.to_s
101     log { "resolver #{FAMILY_TYPES[RECORD_TYPES[family]]}: applying resolution delay..." }
102 
103     @current_selector.after(0.05) do
104       # double emission check
105       unless connection.addresses && addresses.intersect?(connection.addresses)
106         emit_resolved_connection(connection, addresses, early_resolve)
107       end
108     end
109   else
110     emit_resolved_connection(connection, addresses, early_resolve)
111   end
112 end
empty?()
[show source]
   # File lib/httpx/resolver/resolver.rb
69 def empty?
70   true
71 end
force_close(*args)
[show source]
   # File lib/httpx/resolver/resolver.rb
59 def force_close(*args)
60   while (connection = @connections.shift)
61     connection.force_close(*args)
62   end
63 end
handle_error(error)
[show source]
    # File lib/httpx/resolver/resolver.rb
114 def handle_error(error)
115   if error.respond_to?(:connection) &&
116      error.respond_to?(:host)
117     @connections.delete(error.connection)
118     emit_resolve_error(error.connection, error.host, error)
119   else
120     while (connection = @connections.shift)
121       emit_resolve_error(connection, connection.peer.host, error)
122     end
123   end
124 end
inflight?()
[show source]
   # File lib/httpx/resolver/resolver.rb
73 def inflight?
74   false
75 end
initial_call()
[show source]
   # File lib/httpx/resolver/resolver.rb
55 def initial_call
56   call
57 end
lazy_resolve(connection)
[show source]
    # File lib/httpx/resolver/resolver.rb
150 def lazy_resolve(connection)
151   return unless @current_session && @current_selector
152 
153   conn_to_resolve = @current_session.try_clone_connection(connection, @current_selector, @family)
154   self << conn_to_resolve
155 
156   return if empty?
157 
158   # both the resolver and the connection it's resolving must be pinned to the session
159   @current_session.pin(conn_to_resolve, @current_selector)
160   @current_session.select_resolver(self, @current_selector)
161 end
on_error(error)
[show source]
    # File lib/httpx/resolver/resolver.rb
131 def on_error(error)
132   handle_error(error)
133   disconnect
134 end
on_io_error(e)
[show source]
    # File lib/httpx/resolver/resolver.rb
126 def on_io_error(e)
127   on_error(e)
128   force_close(true)
129 end