Apache redirects behind SSL terminating proxy

apache-2.2httphttpsredirectreverse-proxy

I have the following redirects in the <VirtualHost *:80>:

RewriteRule ^/old-url$  /new-url  [R=301,L]
RewriteRule ^/foo$      /bar      [R=301,L]
...

In front of apache I've got haproxy, listening on 80 and 443, the latter doing SSL termination and:

http-request set-header X-Forwarded-Port %[dst_port]
http-request set-header X-Forwarded-Proto https if { ssl_fc }

My problem with the redirects is that:

  1. http://example.com/foo correctly redirects to http://example.com/bar
  2. https://example.com/foo wrongly redirects to http://example.com/bar

How can I make sure http redirects to http and https to https? Note that I want to avoid having to write the redirect rules twice. How could I use the X-Forwarded-Proto or X-Forwarded-Port to redirect to the correct scheme?

Best Answer

Since the redirect will always contain the absolute URL, you'll need to make your redirections to be a full URL, like this:

RewriteEngine On
RewriteRule "^/foo" "%{HTTP:X-Forwarded-Proto}://%{HTTP_HOST}/bar" [R=301]

For this to work in all cases, you need to be sure that the X-Forwarded-Proto is always correct, so it should contain "http" for simple HTTP connections (I believe haproxy doesn't set it explicitly, so you'll need to do so). Also, the Apache server should receive a Host: header, so if haproxy calls the Apache server by IP, then you need to replace the %{HTTP_HOST} part with the actual hostname.