Reputation: 93
I am using traefik 2.0.2 as reverse proxy in front of some services. One backend services is returning a redirect response (302), where the location header contains the absolute redirected url. The url of the backend is not reachable from the outside, how can I rewrite the location to go through the reverse proxy again?
E.g. a client requests http://my-domain/foo
and receives a 302 response with location header containing http://backend:8080/foo/bar/
, which of course will not work.
I am looking for something similar to ProxyPassReverse of apache mod_proxy. I have read through the available middlewares of traefik, but nothing seems to fit my requirement.
My simplified configuration:
# traefik.yml
entryPoints:
web:
address: ":80"
providers:
file:
filename: "dynamic-conf.yml"
# dynamic-conf.yml
http:
routers:
router1:
entryPoints:
- web
service: service1
rule: "PathPrefix(`/foo`)"
services:
service1
loadBalancer:
servers:
- url: http://backend:8080
Upvotes: 4
Views: 6917
Reputation: 1564
For example, in case a WebDav service is behind a TLS reverse-proxy (e.g. Traefik, port 443
), and the service itself is running on non-TLS protocol (i.e. port 80
), and renaming a file (i.e. HTTP method MOVE
) in Nginx may result in error:
..."MOVE /dav/test.txt HTTP/1.1" 400...
...[error] 39#39: *4 client sent invalid "Destination" header...
Related: Seafdav - MOVE command causing 502.
traefik.yaml
)experimental:
plugins:
rewriteHeaders:
modulename: 'github.com/bitrvmpd/traefik-plugin-rewrite-headers'
version: 'v0.0.1'
services:
app:
image: php
volumes:
- '/var/docker/data/app/config/:/etc/nginx/conf.d/:ro'
- '/var/docker/data/app/data/:/var/www/'
networks:
reverse-proxy:
labels:
- 'traefik.enable=true'
- 'traefik.http.services.app.loadbalancer.server.port=80'
# Replace 'Destination' request header: 'https://' -> 'http://'
- 'traefik.http.middlewares.rewriteHeadersMW.plugin.traefik-plugin-rewrite-headers.rewrites.request[0].header=Destination'
- 'traefik.http.middlewares.rewriteHeadersMW.plugin.traefik-plugin-rewrite-headers.rewrites.request[0].regex=^https://(.+)$'
- 'traefik.http.middlewares.rewriteHeadersMW.plugin.traefik-plugin-rewrite-headers.rewrites.request[0].replacement=http://$1'
- 'traefik.http.routers.app.rule=Host(`sub.example.com`)'
- 'traefik.http.routers.app.entrypoints=https'
- 'traefik.http.routers.app.priority=2'
- 'traefik.http.routers.app.middlewares=rewriteHeadersMW'
networks:
reverse-proxy:
name: reverse-proxy
external: true
Non-Traefik alternative: Nginx module headers-more-nginx-module
.
Upvotes: 0
Reputation: 2617
I had the same issue as you, could not resolve it with your solution, but now, with the traefik plugins, we can:
Static config:
pilot:
token: "xxxx"
experimental:
plugins:
rewriteHeaders:
modulename: "github.com/XciD/traefik-plugin-rewrite-headers"
version: "v0.0.2"
Dynamic config:
http:
routes:
my-router:
rule: "Host(`localhost`)"
service: "my-service"
middlewares :
- "rewriteHeaders"
services:
my-service:
loadBalancer:
servers:
- url: "http://127.0.0.1"
middlewares:
rewriteHeaders:
plugin:
rewriteHeaders:
header: "Location"
regex: "^http://(.+)$"
replacement: "https://$1"
Disclaimer: I'm the author of the plugin
Upvotes: 2
Reputation: 93
I did not find an option to rewrite the location header of a service response using traefik. A feature request to replaceResponseHeaders exists.
My (temporary) solution is to perform the redirection in traefik using the RedirectRegex middleware, such that the backend service does not need to response with a redirect.
The updated configuration would look like this:
# dynamic-conf.yml
http:
routers:
router1:
entryPoints:
- web
service: service1
rule: "PathPrefix(`/foo`)"
middlewares:
- my-redirect
middlewares:
my-redirect: # Workaround for service1 redirection
redirectRegex:
regex: "^https?://[^/]+/foo/?$"
replacement: "/foo/webapp/"
services:
service1
loadBalancer:
servers:
- url: http://backend:8080
Upvotes: 2