Class: HTTPX::Resolver::Resolver
- Inherits:
-
Object
- Object
- HTTPX::Resolver::Resolver
- Includes:
- Loggable, _Selectable
- Defined in:
- lib/httpx/resolver/resolver.rb,
sig/resolver/resolver.rbs
Overview
Base class for all internal internet name resolvers. It handles basic blocks from the Selectable API.
Constant Summary collapse
- RECORD_TYPES =
{ Socket::AF_INET6 => Resolv::DNS::Resource::IN::AAAA, Socket::AF_INET => Resolv::DNS::Resource::IN::A, }.freeze
- FAMILY_TYPES =
{ Resolv::DNS::Resource::IN::AAAA => "AAAA", Resolv::DNS::Resource::IN::A => "A", }.freeze
Constants included from Loggable
Loggable::COLORS, Loggable::USE_DEBUG_LOG
Instance Attribute Summary collapse
-
#current_selector ⇒ Object
writeonly
Sets the attribute current_selector.
-
#current_session ⇒ Object
writeonly
Sets the attribute current_session.
-
#family ⇒ ip_family
readonly
Returns the value of attribute family.
-
#multi ⇒ Multi?
Returns the value of attribute multi.
-
#options ⇒ Options
readonly
Returns the value of attribute options.
Class Method Summary collapse
Instance Method Summary collapse
- #close ⇒ void (also: #terminate)
- #close_or_resolve ⇒ void
- #closed? ⇒ Boolean
- #disconnect ⇒ void
- #each_connection {|connection| ... } ⇒ void
-
#early_resolve(connection, hostname: connection.peer.host) ⇒ Boolean
rubocop:disable Naming/PredicateMethod.
- #emit_addresses(connection, family, addresses, early_resolve = false) ⇒ void
- #emit_connection_error(connection, error) ⇒ void
- #emit_resolve_error(connection, hostname = connection.peer.host, ex = nil) ⇒ void
- #emit_resolved_connection(connection, addresses, early_resolve) ⇒ void
- #empty? ⇒ Boolean
- #force_close(*args) ⇒ Object
- #handle_error(error) ⇒ void
- #inflight? ⇒ Boolean
- #initial_call ⇒ Object
-
#initialize(family, options) ⇒ Resolver
constructor
A new instance of Resolver.
- #lazy_resolve(connection) ⇒ void
- #on_error(error) ⇒ Object
- #on_io_error(e) ⇒ Object
- #resolve ⇒ void
- #resolve_connection(connection) ⇒ void
- #resolve_error(hostname, ex = nil) ⇒ ResolveError, ResolveTimeoutError
Methods included from Loggable
#log, #log_exception, log_identifiers, #log_redact, #log_redact_body, #log_redact_headers
Methods included from _Selectable
#call, #handle_socket_timeout, #interests, #state, #timeout, #to_io
Constructor Details
#initialize(family, options) ⇒ Resolver
Returns a new instance of Resolver.
36 37 38 39 40 41 |
# File 'lib/httpx/resolver/resolver.rb', line 36 def initialize(family, ) @family = family @record_type = RECORD_TYPES[family] @options = @connections = [] end |
Instance Attribute Details
#current_selector=(value) ⇒ Object (writeonly)
Sets the attribute current_selector
32 33 34 |
# File 'lib/httpx/resolver/resolver.rb', line 32 def current_selector=(value) @current_selector = value end |
#current_session=(value) ⇒ Object (writeonly)
Sets the attribute current_session
32 33 34 |
# File 'lib/httpx/resolver/resolver.rb', line 32 def current_session=(value) @current_session = value end |
#family ⇒ ip_family (readonly)
Returns the value of attribute family.
30 31 32 |
# File 'lib/httpx/resolver/resolver.rb', line 30 def family @family end |
#multi ⇒ Multi?
Returns the value of attribute multi.
34 35 36 |
# File 'lib/httpx/resolver/resolver.rb', line 34 def multi @multi end |
#options ⇒ Options (readonly)
Returns the value of attribute options.
30 31 32 |
# File 'lib/httpx/resolver/resolver.rb', line 30 def @options end |
Class Method Details
.multi? ⇒ Boolean
25 26 27 |
# File 'lib/httpx/resolver/resolver.rb', line 25 def multi? true end |
Instance Method Details
#close ⇒ void Also known as: terminate
This method returns an undefined value.
51 |
# File 'lib/httpx/resolver/resolver.rb', line 51 def close; end |
#close_or_resolve ⇒ void
This method returns an undefined value.
60 |
# File 'sig/resolver/resolver.rbs', line 60
def close_or_resolve: () -> void
|
#closed? ⇒ Boolean
65 66 67 |
# File 'lib/httpx/resolver/resolver.rb', line 65 def closed? true end |
#disconnect ⇒ void
This method returns an undefined value.
205 206 207 208 209 210 211 |
# File 'lib/httpx/resolver/resolver.rb', line 205 def disconnect close return unless closed? @current_session.deselect_resolver(self, @current_selector) end |
#each_connection {|connection| ... } ⇒ void
This method returns an undefined value.
43 44 45 46 47 48 49 |
# File 'lib/httpx/resolver/resolver.rb', line 43 def each_connection(&block) enum_for(__method__) unless block return unless @connections @connections.each(&block) end |
#early_resolve(connection, hostname: connection.peer.host) ⇒ Boolean
rubocop:disable Naming/PredicateMethod
136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/httpx/resolver/resolver.rb', line 136 def early_resolve(connection, hostname: connection.peer.host) # rubocop:disable Naming/PredicateMethod addresses = @resolver_options[:cache] && (connection.addresses || @options.resolver_cache.resolve(hostname)) return false unless addresses addresses = addresses.select { |addr| addr.family == @family } return false if addresses.empty? emit_addresses(connection, @family, addresses, true) true end |
#emit_addresses(connection, family, addresses, early_resolve = false) ⇒ void
This method returns an undefined value.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/httpx/resolver/resolver.rb', line 77 def emit_addresses(connection, family, addresses, early_resolve = false) addresses.map! { |address| address.is_a?(Resolver::Entry) ? address : Resolver::Entry.new(address) } # double emission check, but allow early resolution to work conn_addrs = connection.addresses return if !early_resolve && conn_addrs && !conn_addrs.empty? && !addresses.intersect?(conn_addrs) log do "resolver #{FAMILY_TYPES[RECORD_TYPES[family]]}: " \ "answer #{connection.peer.host}: #{addresses.inspect} (early resolve: #{early_resolve})" end # do not apply resolution delay for non-dns name resolution if !early_resolve && # just in case... @current_selector && # resolution delay only applies to IPv4 family == Socket::AF_INET && # connection already has addresses and initiated/ended handshake !connection.io && # no need to delay if not supporting dual stack / multi-homed IP (connection..ip_families || Resolver.supported_ip_families).size > 1 && # connection URL host is already the IP (early resolve included perhaps?) addresses.first.to_s != connection.peer.host.to_s log { "resolver #{FAMILY_TYPES[RECORD_TYPES[family]]}: applying resolution delay..." } @current_selector.after(0.05) do # double emission check unless connection.addresses && addresses.intersect?(connection.addresses) emit_resolved_connection(connection, addresses, early_resolve) end end else emit_resolved_connection(connection, addresses, early_resolve) end end |
#emit_connection_error(connection, error) ⇒ void
This method returns an undefined value.
199 200 201 202 203 |
# File 'lib/httpx/resolver/resolver.rb', line 199 def emit_connection_error(connection, error) return connection.handle_connect_error(error) if connection.connecting? connection.on_error(error) end |
#emit_resolve_error(connection, hostname = connection.peer.host, ex = nil) ⇒ void
This method returns an undefined value.
182 183 184 |
# File 'lib/httpx/resolver/resolver.rb', line 182 def emit_resolve_error(connection, hostname = connection.peer.host, ex = nil) emit_connection_error(connection, resolve_error(hostname, ex)) end |
#emit_resolved_connection(connection, addresses, early_resolve) ⇒ void
This method returns an undefined value.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/httpx/resolver/resolver.rb', line 165 def emit_resolved_connection(connection, addresses, early_resolve) begin connection.addresses = addresses return if connection.state == :closed resolve_connection(connection) rescue StandardError => e if early_resolve connection.force_close throw(:resolve_error, e) else emit_connection_error(connection, e) end end end |
#empty? ⇒ Boolean
69 70 71 |
# File 'lib/httpx/resolver/resolver.rb', line 69 def empty? true end |
#force_close(*args) ⇒ Object
59 60 61 62 63 |
# File 'lib/httpx/resolver/resolver.rb', line 59 def force_close(*args) while (connection = @connections.shift) connection.force_close(*args) end end |
#handle_error(error) ⇒ void
This method returns an undefined value.
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/httpx/resolver/resolver.rb', line 114 def handle_error(error) if error.respond_to?(:connection) && error.respond_to?(:host) @connections.delete(error.connection) emit_resolve_error(error.connection, error.host, error) else while (connection = @connections.shift) emit_resolve_error(connection, connection.peer.host, error) end end end |
#inflight? ⇒ Boolean
73 74 75 |
# File 'lib/httpx/resolver/resolver.rb', line 73 def inflight? false end |
#initial_call ⇒ Object
55 56 57 |
# File 'lib/httpx/resolver/resolver.rb', line 55 def initial_call call end |
#lazy_resolve(connection) ⇒ void
This method returns an undefined value.
150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/httpx/resolver/resolver.rb', line 150 def lazy_resolve(connection) return unless @current_session && @current_selector conn_to_resolve = @current_session.try_clone_connection(connection, @current_selector, @family) self << conn_to_resolve return if empty? # both the resolver and the connection it's resolving must be pinned to the session @current_session.pin(conn_to_resolve, @current_selector) @current_session.select_resolver(self, @current_selector) end |
#on_error(error) ⇒ Object
131 132 133 134 |
# File 'lib/httpx/resolver/resolver.rb', line 131 def on_error(error) handle_error(error) disconnect end |
#on_io_error(e) ⇒ Object
126 127 128 129 |
# File 'lib/httpx/resolver/resolver.rb', line 126 def on_io_error(e) on_error(e) force_close(true) end |
#resolve ⇒ void
This method returns an undefined value.
46 |
# File 'sig/resolver/resolver.rbs', line 46
def resolve: (?Connection connection, ?String hostname) -> void
|
#resolve_connection(connection) ⇒ void
This method returns an undefined value.
195 196 197 |
# File 'lib/httpx/resolver/resolver.rb', line 195 def resolve_connection(connection) @current_session.__send__(:on_resolver_connection, connection, @current_selector) end |
#resolve_error(hostname, ex = nil) ⇒ ResolveError, ResolveTimeoutError
186 187 188 189 190 191 192 193 |
# File 'lib/httpx/resolver/resolver.rb', line 186 def resolve_error(hostname, ex = nil) return ex if ex.is_a?(ResolveError) || ex.is_a?(ResolveTimeoutError) = ex ? ex. : "Can't resolve #{hostname}" error = ResolveError.new() error.set_backtrace(ex ? ex.backtrace : caller) error end |