Module: HTTPX::Resolver

Extended by:
Registry
Defined in:
lib/httpx/resolver.rb

Defined Under Namespace

Classes: HTTPS, Multi, Native, Resolver, System

Constant Summary collapse

RESOLVE_TIMEOUT =
5

Class Method Summary collapse

Methods included from Registry

extended, included

Class Method Details

.cached_lookup(hostname) ⇒ Object



48
49
50
51
52
53
# File 'lib/httpx/resolver.rb', line 48

def cached_lookup(hostname)
  now = Utils.now
  @lookup_mutex.synchronize do
    lookup(hostname, now)
  end
end

.cached_lookup_set(hostname, family, entries) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/httpx/resolver.rb', line 55

def cached_lookup_set(hostname, family, entries)
  now = Utils.now
  entries.each do |entry|
    entry["TTL"] += now
  end
  @lookup_mutex.synchronize do
    case family
    when Socket::AF_INET6
      @lookups[hostname].concat(entries)
    when Socket::AF_INET
      @lookups[hostname].unshift(*entries)
    end
    entries.each do |entry|
      next unless entry["name"] != hostname

      case family
      when Socket::AF_INET6
        @lookups[entry["name"]] << entry
      when Socket::AF_INET
        @lookups[entry["name"]].unshift(entry)
      end
    end
  end
end

.decode_dns_answer(payload) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/httpx/resolver.rb', line 109

def decode_dns_answer(payload)
  message = Resolv::DNS::Message.decode(payload)
  addresses = []
  message.each_answer do |question, _, value|
    case value
    when Resolv::DNS::Resource::IN::CNAME
      addresses << {
        "name" => question.to_s,
        "TTL" => value.ttl,
        "alias" => value.name.to_s,
      }
    when Resolv::DNS::Resource::IN::A,
         Resolv::DNS::Resource::IN::AAAA
      addresses << {
        "name" => question.to_s,
        "TTL" => value.ttl,
        "data" => value.address.to_s,
      }
    end
  end
  addresses
end

.encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/httpx/resolver.rb', line 101

def encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A)
  Resolv::DNS::Message.new.tap do |query|
    query.id = generate_id
    query.rd = 1
    query.add_question(hostname, type)
  end.encode
end

.generate_idObject



97
98
99
# File 'lib/httpx/resolver.rb', line 97

def generate_id
  @identifier_mutex.synchronize { @identifier = (@identifier + 1) & 0xFFFF }
end

.ip_resolve(hostname) ⇒ Object



35
36
37
38
# File 'lib/httpx/resolver.rb', line 35

def ip_resolve(hostname)
  [IPAddr.new(hostname)]
rescue ArgumentError
end

.lookup(hostname, ttl) ⇒ Object

do not use directly!



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/httpx/resolver.rb', line 81

def lookup(hostname, ttl)
  return unless @lookups.key?(hostname)

  @lookups[hostname] = @lookups[hostname].select do |address|
    address["TTL"] > ttl
  end
  ips = @lookups[hostname].flat_map do |address|
    if address.key?("alias")
      lookup(address["alias"], ttl)
    else
      IPAddr.new(address["data"])
    end
  end
  ips unless ips.empty?
end

.nolookup_resolve(hostname) ⇒ Object



31
32
33
# File 'lib/httpx/resolver.rb', line 31

def nolookup_resolve(hostname)
  ip_resolve(hostname) || cached_lookup(hostname) || system_resolve(hostname)
end

.system_resolve(hostname) ⇒ Object



40
41
42
43
44
45
46
# File 'lib/httpx/resolver.rb', line 40

def system_resolve(hostname)
  ips = @system_resolver.getaddresses(hostname)
  return if ips.empty?

  ips.map { |ip| IPAddr.new(ip) }
rescue IOError
end