Module: RightSupport::Net::DNS
- Defined in:
- lib/right_support/net/dns.rb
Constant Summary collapse
- DEFAULT_RESOLVE_OPTIONS =
{ :address_family => Socket::AF_INET, :socket_type => Socket::SOCK_STREAM, :protocol => Socket::IPPROTO_TCP, :retry => 3 }
Class Method Summary collapse
-
.resolve(endpoints, opts = {}) ⇒ Array<String>
Perform DNS resolution on a set of endpoints, where the endpoints may be hostnames or URIs.
-
.resolve_all_ip_addresses(hostnames) ⇒ Object
deprecated
Deprecated.
due to broken error handling - do not use; please use #resolve instead!
-
.resolve_with_hostnames(endpoints, opts = {}) ⇒ Hash<hostnames => [endpoints]>
Similar to resolve, but return a hash of { hostnames => [endpoints] }.
Class Method Details
.resolve(endpoints, opts = {}) ⇒ Array<String>
Perform DNS resolution on a set of endpoints, where the endpoints may be hostnames or URIs. Expand out the list to include one entry per distinct address that is assigned to a given hostname, but preserve other aspects of the endpoints –. URIs will remain URIs with the same protocol, path-info, and so forth, but the hostname component will be resolved to IP addresses and the URI will be duplicated in the output, once for each distinct IP address.
Although this method does accept IPv4 dotted-quad addresses as input, it does not accept IPv6 addresses. However, given hostnames or URIs as input, one can resolve the hostnames to IPv6 addresses by specifying the appropriate address_family in the options.
It should never be necessary to specify a different :socket_type or :protocol, but these options are exposed just in case.
83 84 85 86 87 88 |
# File 'lib/right_support/net/dns.rb', line 83 def self.resolve(endpoints, opts={}) resolved_hostnames = resolve_with_hostnames(endpoints, opts) resolved_endpoints = [] resolved_hostnames.each_value{ |v| resolved_endpoints.concat(v) } return resolved_endpoints end |
.resolve_all_ip_addresses(hostnames) ⇒ Object
due to broken error handling - do not use; please use #resolve instead!
Resolve a set of DNS hostnames to the individual IP addresses to which they map. Only handles IPv4 addresses.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/right_support/net/dns.rb', line 39 def self.resolve_all_ip_addresses(hostnames) ips = [] hostnames = [hostnames] unless hostnames.respond_to?(:each) hostnames.each do |hostname| infos = nil begin infos = Socket.getaddrinfo(hostname, 443, Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP) rescue Exception => e # NOTE: Need to figure out, which logger can we use here? # Log.error "Rescued #{e.class.name} resolving Repose hostnames: #{e.message}; retrying" retry end #Randomly permute the addrinfos of each hostname to help spread load. infos.shuffle.each do |info| ips << info[3] end end ips end |
.resolve_with_hostnames(endpoints, opts = {}) ⇒ Hash<hostnames => [endpoints]>
Similar to resolve, but return a hash of { hostnames => [endpoints] }
Perform DNS resolution on a set of endpoints, where the endpoints may be hostnames or URIs. Expand out the list to include one entry per distinct address that is assigned to a given hostname, but preserve other aspects of the endpoints –. URIs will remain URIs with the same protocol, path-info, and so forth, but the hostname component will be resolved to IP addresses and the URI will be duplicated in the output, once for each distinct IP address.
Although this method does accept IPv4 dotted-quad addresses as input, it does not accept IPv6 addresses. However, given hostnames or URIs as input, one can resolve the hostnames to IPv6 addresses by specifying the appropriate address_family in the options.
It should never be necessary to specify a different :socket_type or :protocol, but these options are exposed just in case.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/right_support/net/dns.rb', line 115 def self.resolve_with_hostnames(endpoints, opts={}) opts = DEFAULT_RESOLVE_OPTIONS.merge(opts) endpoints = [endpoints] unless endpoints.respond_to?(:each) hostname_hash = {} retries = 0 endpoints.each do |endpoint| begin resolved_endpoints = [] if endpoint.include?(':') # It contains a colon, therefore it must be a URI -- we don't support IPv6 uri = URI.parse(endpoint) hostname = uri.host raise URI::InvalidURIError, "Could not parse host component of URI" unless hostname infos = Socket.getaddrinfo(hostname, nil, opts[:address_family], opts[:socket_type], opts[:protocol]) infos.each do |info| transformed_uri = uri.dup transformed_uri.host = info[3] resolved_endpoints << transformed_uri.to_s end else # No colon; it's a hostname or IP address infos = Socket.getaddrinfo(endpoint, nil, opts[:address_family], opts[:socket_type], opts[:protocol]) infos.each do |info| resolved_endpoints << info[3] end end hostname_hash[endpoint.to_s] = resolved_endpoints rescue SocketError => e retries += 1 if retries < opts[:retry] retry else raise end end end hostname_hash end |