Routing Rules
A router's rule is a small test a request must pass. Chapter 4 used the simplest one — a host name. This chapter adds the rest of the toolbox, and the rule that decides between routers when two of them both pass.
The matchers that matter
| Matcher | Tests | Example |
|---|---|---|
Host |
The name asked for | Host(`fern.test`) |
Path |
The exact path | Path(`/about`) |
PathPrefix |
The start of the path | PathPrefix(`/api`) |
Headers |
A header's value | Headers(`X-Team`, `fern`) |
Query |
A query parameter | Query(`preview`, `yes`) |
Method |
The HTTP verb | Method(`POST`) |
ClientIP |
The visitor's address | ClientIP(`192.168.1.0/24`) |
Rules combine with && (and), ||
(or) and ! (not), with brackets where
you need them:
rule: "Host(`fern.test`) && PathPrefix(`/api`)"
One name, two backends
The lab's second act (transcript t02): fern's site grows an API that actually lives in the otter program. One more router —
fern-api:
rule: "Host(`fern.test`) && PathPrefix(`/api`)"
entryPoints:
- web
service: otter
— and fern.test/api/weather is answered
by otter while fern.test/about still
goes to fern. Same host, same entrypoint,
two backends, split by path. This is the
standard shape for "the app is here, its
API is there", and for bolting a new
service onto an old name one path at a
time.
Priority: the longer rule wins
Both fern routers pass a request for
/api/weather — the plain Host rule
matches everything on that name. Traefik
breaks the tie by priority, and the
default priority is the rule's length in
characters: the longer, more specific
rule is tried first. That is why the
split above works with no numbers
anywhere.
You can set priority: explicitly on a
router when length gives the wrong
answer — a short rule you truly want
first — but reach for it knowingly: the
day a config grows two hand-set
priorities that conflict, the behaviour
is yours to debug, and the dashboard
(chapter 8) sorts routers by priority so
you can at least see the order Traefik
chose.
Rules that bite, gently
Pathis exact,PathPrefixis a prefix.PathPrefix(/api)also matches/apiculture. If that is not what you meant, the rule you want isPathPrefix(`/api/`)— trailing slash — or an exactPath.- Matchers are literal about case.
Host names are case-insensitive (DNS
is), paths are not.
/APIand/apiare different paths to Traefik and to most backends. - A rule is a string, and strings have syntax. Backticks quote the values; a missing bracket is a parse error, the file is refused, and the last good configuration keeps serving (transcript t07). The log names the rule and the position of the problem — chapter 15 shows the actual message.
- No match is an answer, not an error. A request that passes no router gets Traefik's own 404 (chapter 4). Silence in the log is consistent with correct behaviour; check the router list in the API before assuming a rule is broken.