Base class for all internal internet name resolvers. It handles basic blocks from the Selectable API.
Methods
Public Class
Public Instance
Included modules
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
| current_selector | [W] | |
| current_session | [W] | |
| family | [R] | |
| multi | [RW] | |
| options | [R] |
Public Class methods
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
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
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
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