Skip to content

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

  • Path is exact, PathPrefix is a prefix. PathPrefix(/api) also matches /apiculture. If that is not what you meant, the rule you want is PathPrefix(`/api/`) — trailing slash — or an exact Path.
  • Matchers are literal about case. Host names are case-insensitive (DNS is), paths are not. /API and /api are 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.