module HTTPX::Resolver

  1. lib/httpx/resolver.rb
  2. lib/httpx/resolver/entry.rb
  3. lib/httpx/resolver/https.rb
  4. lib/httpx/resolver/multi.rb
  5. lib/httpx/resolver/native.rb
  6. lib/httpx/resolver/resolver.rb
  7. lib/httpx/resolver/system.rb
  8. lib/httpx/selector.rb
  9. show all

Constants

RESOLVE_TIMEOUT = [2, 3].freeze  

Public Instance methods

cached_lookup(hostname)
[show source]
   # File lib/httpx/resolver.rb
73 def cached_lookup(hostname)
74   now = Utils.now
75   lookup_synchronize do |lookups|
76     lookup(hostname, lookups, now)
77   end
78 end
cached_lookup_evict(hostname, ip)
[show source]
    # File lib/httpx/resolver.rb
101 def cached_lookup_evict(hostname, ip)
102   ip = ip.to_s
103 
104   lookup_synchronize do |lookups|
105     entries = lookups[hostname]
106 
107     return unless entries
108 
109     lookups.delete_if { |entry| entry["data"] == ip }
110   end
111 end
cached_lookup_set(hostname, family, entries)
[show source]
   # File lib/httpx/resolver.rb
80 def cached_lookup_set(hostname, family, entries)
81   lookup_synchronize do |lookups|
82     case family
83     when Socket::AF_INET6
84       lookups[hostname].concat(entries)
85     when Socket::AF_INET
86       lookups[hostname].unshift(*entries)
87     end
88     entries.each do |entry|
89       next unless entry["name"] != hostname
90 
91       case family
92       when Socket::AF_INET6
93         lookups[entry["name"]] << entry
94       when Socket::AF_INET
95         lookups[entry["name"]].unshift(entry)
96       end
97     end
98   end
99 end
decode_dns_answer(payload)
[show source]
    # File lib/httpx/resolver.rb
143 def decode_dns_answer(payload)
144   begin
145     message = Resolv::DNS::Message.decode(payload)
146   rescue Resolv::DNS::DecodeError => e
147     return :decode_error, e
148   end
149 
150   # no domain was found
151   return :no_domain_found if message.rcode == Resolv::DNS::RCode::NXDomain
152 
153   return :message_truncated if message.tc == 1
154 
155   return :dns_error, message.rcode if message.rcode != Resolv::DNS::RCode::NoError
156 
157   addresses = []
158 
159   now = Utils.now
160   message.each_answer do |question, _, value|
161     case value
162     when Resolv::DNS::Resource::IN::CNAME
163       addresses << {
164         "name" => question.to_s,
165         "TTL" => (now + value.ttl),
166         "alias" => value.name.to_s,
167       }
168     when Resolv::DNS::Resource::IN::A,
169          Resolv::DNS::Resource::IN::AAAA
170       addresses << {
171         "name" => question.to_s,
172         "TTL" => (now + value.ttl),
173         "data" => value.address.to_s,
174       }
175     end
176   end
177 
178   [:ok, addresses]
179 end
encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A, message_id: generate_id)
[show source]
    # File lib/httpx/resolver.rb
136 def encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A, message_id: generate_id)
137   Resolv::DNS::Message.new(message_id).tap do |query|
138     query.rd = 1
139     query.add_question(hostname, type)
140   end.encode
141 end
generate_id()
[show source]
    # File lib/httpx/resolver.rb
132 def generate_id
133   id_synchronize { @identifier = (@identifier + 1) & 0xFFFF }
134 end
hosts_resolve(hostname)

matches hostname to entries in the hosts file, returns <tt>nil</nil> if none is found, or there is no hosts file.

[show source]
   # File lib/httpx/resolver.rb
65 def hosts_resolve(hostname)
66   ips = @hosts_resolver.getaddresses(hostname)
67   return if ips.empty?
68 
69   ips.map { |ip| Entry.new(ip) }
70 rescue IOError
71 end
id_synchronize(&block)
[show source]
    # File lib/httpx/resolver.rb
185 def id_synchronize(&block)
186   @identifier_mutex.synchronize(&block)
187 end
ip_resolve(hostname)

tries to convert hostname into an IPAddr, returns nil otherwise.

[show source]
   # File lib/httpx/resolver.rb
58 def ip_resolve(hostname)
59   [Entry.new(hostname)]
60 rescue ArgumentError
61 end
lookup(hostname, lookups, ttl)

do not use directly!

[show source]
    # File lib/httpx/resolver.rb
114 def lookup(hostname, lookups, ttl)
115   return unless lookups.key?(hostname)
116 
117   entries = lookups[hostname] = lookups[hostname].select do |address|
118     address["TTL"] > ttl
119   end
120 
121   ips = entries.flat_map do |address|
122     if (als = address["alias"])
123       lookup(als, lookups, ttl)
124     else
125       Entry.new(address["data"], address["TTL"])
126     end
127   end.compact
128 
129   ips unless ips.empty?
130 end
lookup_synchronize()
[show source]
    # File lib/httpx/resolver.rb
181 def lookup_synchronize
182   @lookup_mutex.synchronize { yield(@lookups) }
183 end
nolookup_resolve(hostname)
[show source]
   # File lib/httpx/resolver.rb
53 def nolookup_resolve(hostname)
54   ip_resolve(hostname) || cached_lookup(hostname) || hosts_resolve(hostname)
55 end
resolver_for(resolver_type, options)
[show source]
   # File lib/httpx/resolver.rb
40 def resolver_for(resolver_type, options)
41   case resolver_type
42   when Symbol
43     meth = :"resolver_#{resolver_type}_class"
44 
45     return options.__send__(meth) if options.respond_to?(meth)
46   when Class
47     return resolver_type if resolver_type < Resolver
48   end
49 
50   raise Error, "unsupported resolver type (#{resolver_type})"
51 end
supported_ip_families()
[show source]
   # File lib/httpx/resolver.rb
26 def supported_ip_families
27   @supported_ip_families ||= begin
28     # https://github.com/ruby/resolv/blob/095f1c003f6073730500f02acbdbc55f83d70987/lib/resolv.rb#L408
29     list = Socket.ip_address_list
30     if list.any? { |a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? }
31       [Socket::AF_INET6, Socket::AF_INET]
32     else
33       [Socket::AF_INET]
34     end
35   rescue NotImplementedError
36     [Socket::AF_INET]
37   end.freeze
38 end