I'm attempting to run Apache in Docker, behind a Traefik reverse proxy for https. Everything works, except that when I access a folder URL without a trailing slash, Apache redirects me to non-https (i.e. https://www.example.com/folder -> http://www.example.com/folder/). This is caused Apache mod_dir DirectorySlash, as described here & here. The solution is to use a rewrite rule, which kicks in before DirectorySlash, like this:
# Redirect to HTTPS before Apache mod_dir DirectorySlash redirect to HTTP
RewriteCond %{HTTP:X-Forwarded-Proto} =https
RewriteCond %{LA-U:REQUEST_FILENAME} -d
RewriteRule ^/(.*[^/])$ https://%{HTTP_HOST}/$1/ [R=301,L,QSA]
However, the issue is Traefik seems not to be setting the X-Forwarded-* headers. Here's a screenshot of the headers I'm getting:
Here are the labels I'm using in my Apache docker-compose file:
labels:
- traefik.enable=true
- traefik.port=80
- traefik.frontend.rule=PathPrefix:/web #Apache is accessible under https://example.com/web/
I've tried various combinations of labels, but no matter what I do, the x-forwarded-* headers always seem to be missing. For example (ref, ref):
- "traefik.frontend.headers.SSLProxyHeaders=X-Forwarded-Proto:https"
- "traefik.frontend.headers.SSLRedirect=true"
I've even tried just getting Traefik to add my own custom headers and can't get those to show up (ref):
- "traefik.https.middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test"
...However, just to convince myself that I'm not crazy & this is actually running behind Traefik, & Traefik can add headers that I can see, this does work & cause the X-Frame-Options header to appear in Firefox:
- traefik.frontend.headers.frameDeny=true
So in summary, the question is: why isn't Traefik setting the x-forwarded-* headers (which I can then use in my Apache RewriteRules) - and how can I get it to do so?
For anyone who finds this & is wondering, my issue was twofold:
1) X-Forwarded-* headers are not viewable in the browser. You can see them on the server with i.e. phpinfo(), or by dumping the $_SERVER variable:
2) The reason the redirects weren't working (to fix the DirectorySlash issue) is because in addition to the RewriteRules listed above, your htaccess must include RewriteOptions AllowNoSlash. From the Apache documentation:
By default, mod_rewrite will ignore URLs that map to a directory on disk but lack a trailing slash, in the expectation that the mod_dir module will issue the client with a redirect to the canonical URL with a trailing slash. [...] the AllowNoSlash option can be enabled to ensure that rewrite rules are no longer ignored. This option makes it possible to apply rewrite rules within .htaccess files that match the directory without a trailing slash, if so desired.