Shun.Rule.Target (Shun v1.0.1) View Source
Encapsulates target classification logic used by Shun.Rule
to interpret target patterns.
All Rules are built with Targets, which are usually quoted patterns when the relevant generator
functions are being used from macros, such as ones in Shun.Builder
. These can represent URIs,
IPv4 or IPv6 addresses, CIDR blocks, or single IP addresses.
Unquoted 4-arity / 8-arity tuples, String literals, and URI structs are also valid. This is to
aid creation of Preset modules, which implement Shun.Preset
and must return valid lists of
Shun.Rule.t/0
.
The following forms of Targets, for example, are valid:
{192, 168, 1, 1}
, which represents an IPv4 Address at192.168.1.1
.{10, _, _, _}
, which represents an IPv4 Address at10.x.x.x
.{_, _, _, _}
, which represents any IPv4 Address.
IPv6 addresses, represented as 8-arity tuples, are also valid:
{0, 0, 0, 0, 0, 0, 0, 1}
, which represents an IPv6 loopback address.{0x8bad, 0xf00d, _, _, _, _, _, _}
, which represents another IPv6 address.{_, _, _, _, _, _, _, _}
, which represents any IPv6 address.
Patterns that match URI
structs can also be used as Targets:
%URI{scheme: "https"}
%URI{scheme: "https", host: "example.com", path: "/admin"}
%URI{scheme: "https", host: "example.com", path: "/books/" <> _}
Lastly, Strings that represent IP Addresses or CIDR blocks can be used as Targets:
192.168.1.1
192.168.100.14/24
2002::1234:abcd:ffff:c0a8:101/64
Strings that are URLs are not accepted; for these purposes you should build URI patterns. This is to ensure that whenever a string literal is used, it represents an IPv4 or IPv6 address, or IPv4 / IPv6 CIDR literal.
Alternatively, for example when building a new Preset, you can pass an URI struct as a Target, which will be compiled down to a pattern that matches the non-nil keys of that URI struct.
Specifically:
iex(1)> lhs = Shun.Rule.reject(%URI{host: "169.254.169.254"}).pattern
iex(2)> {:%, [], [{:__aliases__, _, [:URI]}, {:%{}, [], [host: "169.254.169.254"]}]} = lhs
iex(1)> rhs = quote do: %URI{host: "169.254.169.254"}
iex(2)> {:%, [], [{:__aliases__, _, [:URI]}, {:%{}, [], [host: "169.254.169.254"]}]} = rhs
Guards
When the Rule is given a Target in the form of an Elixir pattern, guards can be used.
For Rules based on URIs, this is a great way to enforce hosts or schemes; for Rules based on IPv4 or IPv6 patterns, this is an alternative to specifying CIDR ranges.
The following Target forms with guard clauses, for example, are valid:
{a, _, _, _} when a == 10
{a, b, _, _} when a < b
{a, b, _, _} when (a * (b + c)) > 10
{a, _, _, _, _, _, _, _} when a >= 0xfe80 and a <= 0xfebf
%URI{host: "example.com", path: "/books/" <> _} when scheme != "ftp"
Link to this section Summary
Types
Represents an AST fragment to be reintegrated as guard.
Represents an AST fragment to be reintegrated as match pattern.
Represents a Target which can be used with one of the functions that builds a Rule.
Link to this section Types
Specs
guard() :: Macro.t()
Represents an AST fragment to be reintegrated as guard.
Specs
pattern() :: Macro.t()
Represents an AST fragment to be reintegrated as match pattern.
Specs
result() :: {:pattern, type :: :ipv4 | :ipv6 | :uri} | {:pattern, type :: :ipv4 | :ipv6 | :uri, pattern()} | {:pattern, type :: :ipv4 | :ipv6 | :uri, pattern(), guard()} | {:range, :ipv4, from :: Shun.Address.value_ipv4(), to :: Shun.Address.value_ipv4()} | {:range, :ipv6, from :: Shun.Address.value_ipv6(), to :: Shun.Address.value_ipv6()}
Specs
Represents a Target which can be used with one of the functions that builds a Rule.