nova_routing_trie (nova v0.18.1)
View SourceHost-aware routing trie. This is Nova's dispatch table: a map from host to a tree of path segments, where each terminal node holds one payload per comparator (HTTP method).
Paths are declared with three kinds of segment:
"/users"- a literal segment."/users/:id"- a binding. Matches one segment and binds it under<<"id">>in the returned bindings map."/assets/[...]"- a catch-all. Matches zero or more trailing segments, which are returned asPathInfo. Only valid as the last segment of a path.
A path may also be an integer, in which case it denotes an HTTP status code rather than a URL. Nova uses this to register error pages.
Matching is deterministic: at each depth a literal segment is tried first, then each binding in name order, then the catch-all. Matching backtracks, so "/a/:x/c" still matches "/a/b/c" even when a "/a/b/d" route exists.
Summary
Functions
Look up a route.
Rebuild the trie from a transformation of its routes. Fun is handed every route in the table and returns the routes the new table should contain, which makes it the way to filter or rewrite the dispatch table wholesale.
Insert a route. Path is a URL or an HTTP status code, Comparator is an HTTP method or `_'' to match any method.
Create an empty trie. Recognised options are strict (also accepted as use_strict for compatibility) and on_duplicate, which is either keep_first (the default) or overwrite.
Every route in the trie, as {Host, Path, Comparator, Payload}. This is the supported way to introspect a dispatch table; the trie itself is opaque. The result can be fed straight back into from_list/1.
A flat, human-readable listing of the routing table, one entry per method and path. Payloads are not included - use routes/1 when you need them.
Types
-type comparator() :: '_' | binary().
-type comparator_in() :: comparator() | atom() | list().
-type conflict() :: #{reason := atom(), at := [child_key()], existing := child_key() | undefined, incoming := child_key() | undefined, conflicts_with := path(), incoming_path := path(), comparator := comparator(), existing_methods := [comparator()]}.
-type payload() :: term().
-type route() :: {path(), comparator_in(), payload()} | {host_in(), path(), comparator_in(), payload()} | {host_in(), path(), comparator_in(), payload(), map()}.
-opaque trie()
-opaque trie_node()
Functions
-spec find(host_in(), path(), comparator_in(), trie()) -> {ok, bindings(), payload()} | {ok, bindings(), payload(), PathInfo :: [binary()]} | {error, not_found} | {error, comparator_not_found, [comparator()]}.
Look up a route.
A host-specific tree is consulted when one exists for Host, and the `_'' tree otherwise. PathInfo is only returned when the match was made by a [...] catch-all and there were trailing segments to report.
{error, comparator_not_found, AllowedMethods} means the path matched but the method did not, which is what Nova turns into a 405.
Rebuild the trie from a transformation of its routes. Fun is handed every route in the table and returns the routes the new table should contain, which makes it the way to filter or rewrite the dispatch table wholesale.
-spec insert(path(), comparator_in(), payload(), trie()) -> {ok, trie()} | {error, conflict, conflict()}.
Insert a route. Path is a URL or an HTTP status code, Comparator is an HTTP method or `_'' to match any method.
Returns {error, conflict, Conflict} when the trie is in strict mode and the route clashes with an existing one. In non-strict mode a clash is logged and resolved according to the on_duplicate option.
-spec member(host_in(), path(), comparator_in(), trie()) -> boolean().
-spec new() -> trie().
Create an empty trie. Recognised options are strict (also accepted as use_strict for compatibility) and on_duplicate, which is either keep_first (the default) or overwrite.
Every route in the trie, as {Host, Path, Comparator, Payload}. This is the supported way to introspect a dispatch table; the trie itself is opaque. The result can be fed straight back into from_list/1.
A flat, human-readable listing of the routing table, one entry per method and path. Payloads are not included - use routes/1 when you need them.