View Source SafeURL.DNSResolver behaviour (SafeURL v1.0.0)
In some cases you might want to use a custom strategy
for DNS resolution. You can do so by passing your own
implementation of SafeURL.DNSResolver in the global
or local config.
By default, the DNS package is used for resolution,
but you can replace it with a wrapper that uses
different configuration or a completely different
implementation altogether.
Use-cases
- Using a specific DNS server
- Avoiding network access in specific environments
- Mocking DNS resolution in tests
Usage
Start by creating a module that implements the
DNSResolver behaviour. Currently, this means adding
only one resolve/1 callback that takes a host and
returns a list of resolved IPs.
As an example, suppose you wanted to use
Cloudflare's DNS, you can do
that by wrapping DNS with your own settings in a new
module:
defmodule CloudflareDNS do
@behaviour SafeURL.DNSResolver
@impl true
def resolve(domain) do
DNS.resolve(domain, :a, {"1.1.1.1", 53}, :udp)
end
endTo use it, simply pass it in the global config:
config :safeurl, dns_module: CloudflareDNSYou can also directly set the :dns_module in method options:
SafeURL.allowed?("https://example.com", dns_module: CloudflareDNS)Testing
This is especially useful in tests where you want to
ensure your HTTP Client wrapper with SafeURL is
working as expected.
You can override the :dns_module config to ensure
a specific IP is resolved for a domain or no network
requests are made:
defmodule TestDNSResolver do
@behaviour SafeURL.DNSResolver
@impl true
def resolve("google.com"), do: {:ok, [{192, 168, 1, 10}]}
def resolve("github.com"), do: {:ok, [{192, 168, 1, 20}]}
def resolve(_domain), do: {:ok, [{192, 168, 1, 99}]}
end
Summary
Callbacks
@callback resolve(host :: String.t()) :: {:ok, list()} | {:error, :inet_res.res_error()}