traefik/traefik
Routing
Routing is the path from "request landed on an entry point" to "this is the middleware chain and service to use". It comes in three layers: the rule grammar, the muxers that compile rules into matchers, and the router factory that assembles trees from configuration.
The rule grammar
Traefik's rule language lives in pkg/rules/parser.go. Examples:
Host(`api.example.com`)
Host(`api.example.com`) && PathPrefix(`/v1`)
HostRegexp(`{subdomain:[a-z]+}.example.com`)
ClientIP(`10.0.0.0/8`) && Method(`GET`, `POST`)The parser is a small handwritten recursive-descent implementation. It produces an AST of named matchers (Host, Header, HeaderRegexp, Method, Path, PathPrefix, PathRegexp, Query, QueryRegexp, ClientIP, HostRegexp, …) combined with &&, ||, and !.
For TCP, the grammar is similar but limited to matchers that work on the TLS handshake or address (HostSNI, HostSNIRegexp, ClientIP, ALPN).
HTTP muxer
pkg/muxer/http compiles rule ASTs into a matcher function func(*http.Request) bool and stores them in a routing tree.
Highlights:
- Each matcher type has its own implementation file:
host.go,headers.go,path.go, etc. (see the directory). - Routers are sorted by priority (default = rule length) so the most specific rule wins ties.
- The muxer holds a
*atomic.Pointerto its handler tree.pkg/server/router/router.goswaps the pointer after each configuration apply.
The HTTP muxer is the only matcher consulted on the hot path for HTTP traffic. There is no global regex evaluation — rules are split into typed matchers.
TCP muxer
pkg/muxer/tcp operates on the bytes the kernel delivered. Its main job is:
- Parse the TLS ClientHello (when present) to extract SNI and ALPN.
- Match TCP routers against
HostSNI,ClientIP, andALPN. - Select between TLS termination, TLS passthrough, or raw TCP.
Because TLS sniffing must complete before the routing decision, the entry-point implementation in pkg/server/server_entrypoint_tcp.go peeks the first bytes via a buffered conn before handing off to the muxer.
Router factory
pkg/server/routerfactory.go is the listener for configuration changes. Its public API:
type RouterFactory struct {
// ...
}
func (f *RouterFactory) CreateRouters(confDyn *runtime.Configuration) (
map[string]http.Handler,
map[string]*tcprouter.Router,
map[string]udprouter.Handler,
)For each configured entry point it returns the freshly built handler tree. The watcher feeds the result back into the entry points via SwitchRouter.
The HTTP build pipeline is implemented in pkg/server/router/router.go:
graph TD
Conf[runtime.Configuration] --> RouterMgr[manager<br/>pkg/server/router/router.go]
RouterMgr -->|for each router| BuildChain
BuildChain --> Mids[middleware chain<br/>pkg/server/middleware/middlewares.go]
BuildChain --> Svc[service handler<br/>pkg/server/service/service.go]
Mids --> ObsWrap[observability wrapper<br/>pkg/server/middleware/observability.go]
Svc --> LB[load balancer<br/>pkg/server/service/loadbalancer/*]
BuildChain --> Mux[register on muxer<br/>pkg/muxer/http]Each step records a Status/Err on the runtime model. If a middleware reference is unresolved or a TLS option is unknown, the router gets disabled status with the reason — the dashboard shows it under "Errors".
Recursion and denial
pkg/server/router/deny.go and pkg/middlewares/denyrouterrecursion prevent middleware/router cycles. A router referenced by another router that ultimately points back to itself is rejected with a "router recursion detected" error.
TCP and UDP routers
pkg/server/router/tcp and pkg/server/router/udp are smaller siblings of the HTTP router. They consume runtime.TCPConfiguration and runtime.UDPConfiguration and register entries on the corresponding muxers. TCP routers can carry middlewares too — see pkg/middlewares/tcp/.
Internal handlers
A few routes are not user-defined. The pkg/server/service/internalhandler.go wires up:
api@internal— the dashboard / API.dashboard@internal— the static-asset handler for the dashboard.ping@internal—/ping.prometheus@internal—/metrics.acme-http@internal— HTTP-01 challenge handler.noop@internal— a no-op service used as a placeholder.
These internal services have stable names so that other configurations can reference them. The Tailscale and Traefik providers (pkg/provider/tailscale, pkg/provider/traefik) inject routers that point at these internal services.
How a single request resolves
sequenceDiagram
participant C as Client
participant EP as TCP entry point
participant M as HTTP muxer
participant R as Router
participant Mid as Middleware chain
participant S as Service handler
participant LB as Load balancer
participant B as Backend
C->>EP: TCP/TLS handshake
EP->>EP: TLS termination via tlsmanager
EP->>M: HTTP request
M->>M: evaluate rules in priority order
M->>R: matched router
R->>Mid: ServeHTTP(...)
Mid->>Mid: each middleware decides to pass through or short-circuit
Mid->>S: ServeHTTP(...)
S->>LB: pick a backend
LB->>B: forward request
B-->>LB: response
LB-->>S: response
S-->>Mid: response (modifiers run on the way back)
Mid-->>R: response
R-->>M: response
M-->>EP: response
EP-->>C: response (with logging, metrics, tracing all captured)Key files
| File | Purpose |
|---|---|
pkg/rules/parser.go |
Rule grammar parser. |
pkg/muxer/http/muxer.go |
HTTP muxer + matcher tree. |
pkg/muxer/http/host.go, path.go, headers.go, … |
Per-matcher implementations. |
pkg/muxer/tcp/muxer.go |
TCP muxer using SNI/ALPN. |
pkg/server/router/router.go |
HTTP router factory. |
pkg/server/router/deny.go |
Recursion guard. |
pkg/server/router/tcp/router.go |
TCP router factory. |
pkg/server/router/udp/router.go |
UDP router factory. |
pkg/server/routerfactory.go |
Listener wiring + entry-point dispatch. |
pkg/server/service/internalhandler.go |
Internal service registry. |
Entry points for modification
- Adding a new matcher: implement it under
pkg/muxer/http/(orpkg/muxer/tcp/), register it in the parser's matcher table inpkg/rules/parser.go. - Adding a new internal service: register it in
pkg/server/service/internalhandler.go. - Changing how routers are sorted: see the priority logic in
pkg/server/router/router.go.
For the middlewares attached to a router, see Middlewares. For the services those routers point at, see Service and load balancing.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.