Traefik’s headers middleware doesn’t just add or remove headers; it’s a powerful, albeit sometimes overlooked, tool for shaping HTTP requests and responses at the edge, acting as a fine-grained traffic manipulator before your services even see the traffic.
Let’s say you have a simple Traefik setup routing traffic to a backend service running on localhost:8080. Here’s the Traefik configuration:
# traefik.yml
entryPoints:
web:
address: ":80"
providers:
docker:
exposedByDefault: false
api:
dashboard: true
# services.yml
http:
routers:
my-router:
rule: "Host(`localhost`)"
service: "my-service"
entryPoints:
- "web"
services:
my-service:
loadBalancer:
servers:
- url: "http://localhost:8080"
middlewares:
add-custom-header:
headers:
customRequestHeaders:
X-Custom-Request-Header: "MyValue"
remove-user-agent:
headers:
browserForwarding: false # This is how you remove a header
modify-x-forwarded-for:
headers:
customHeaders:
X-Forwarded-For: "1.2.3.4" # This overwrites, not modifies
# routers.yml - linking middleware to router
http:
routers:
my-router:
rule: "Host(`localhost`)"
service: "my-service"
entryPoints:
- "web"
middlewares:
- "add-custom-header@file"
- "remove-user-agent@file"
- "modify-x-forwarded-for@file" # Example of modifying
Now, if you send a request to localhost with curl -v http://localhost, you’ll see Traefik in action:
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.81.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Content-Length: 15
< Date: Tue, 23 May 2023 10:00:00 GMT
< X-Custom-Request-Header: MyValue
< X-Forwarded-For: 1.2.3.4
< Server: Traefik
<
Hello, World!
Notice a few things:
X-Custom-Request-Header: MyValuewas added to the request that Traefik forwarded to your backend.- The
User-Agentheader from yourcurlrequest is gone. Traefik’sbrowserForwarding: falsesetting onheaders.browserForwardingtells it not to pass through browser-specific headers likeUser-Agent,Accept-Language, etc. X-Forwarded-For: 1.2.3.4is present. This is where it gets interesting. SettingcustomHeaderswith a specific header name and value overwrites any existing header with that name. Traefik doesn’t append toX-Forwarded-Forby default; it replaces it. This is a crucial distinction.
The core problem the headers middleware solves is the need for a centralized, configurable point to manage HTTP headers for requests and responses before they reach or leave your application services. This is invaluable for security, observability, and service integration.
Here’s how it works internally: Traefik processes middlewares sequentially based on their order in the router’s middlewares list. For each request, it iterates through the configured middlewares. The headers middleware specifically targets header manipulation.
customRequestHeaders: This section adds new headers or overwrites existing ones on the request going to your backend service.customHeaders: This section, when used without specifyingcustomRequestHeaders, acts on the response headers going back to the client. If you use it on a request-level router, it will overwrite theX-Forwarded-For(and others) as shown above.browserForwarding: When set tofalse, it instructs Traefik to strip out common browser headers likeUser-Agent,Accept-Language,Accept-Encoding, andReferer. Setting it totrue(or omitting it, astrueis the default) allows these headers to pass through.
The most surprising thing about the headers middleware is how customHeaders interacts with X-Forwarded-For. Many expect X-Forwarded-For to be a cumulative list, with Traefik appending the client’s IP. However, the customHeaders configuration, when applied directly to a router, acts as a direct replacement. If you want to correctly append to X-Forwarded-For, you’d typically rely on Traefik’s default behavior or use specific plugins/configurations that handle IP address accumulation more intelligently, or even better, ensure your backend services are configured to trust the X-Forwarded-For header and append to it themselves if needed, or use Traefik’s forwardedHeaders middleware.
To truly append to X-Forwarded-For and maintain the chain of proxies, you’d typically use Traefik’s forwardedHeaders middleware instead of directly manipulating X-Forwarded-For with customHeaders. The forwardedHeaders middleware is designed to correctly manage the X-Forwarded-For and X-Forwarded-Proto headers, adding the client’s IP address to the X-Forwarded-For list.
The next logical step after mastering header manipulation is understanding how to manage request body transformations or how to implement rate limiting to protect your services.