Search code examples
apachemod-rewritereverse-proxymod-proxymod-ssl

Apache ProxyPassReverse not rewriting Location header properly


I'm configuring apache to proxy SSL requests to a local backend server. Here are the relevant parts of the virtual host:

<VirtualHost *:443>

  ...

  SSLEngine on
  SSLCertificateFile /path/to/server.crt
  SSLCertificateKeyFile /path/to/server.key

  RewriteEngine On

  <Proxy balancer://unicornservers>
    BalancerMember http://127.0.0.1:8080
  </Proxy>

  # Redirect all non-static requests to unicorn
  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ balancer://unicornservers%{REQUEST_URI} [P,QSA,L]

  ProxyPassReverse / balancer://unicornservers/
  ProxyPreserveHost on

  ...

</VirtualHost>

When I use curl to access the server (curl -vk https://example.com), the backend server performs a redirect to /login, as it is supposed to.

The problem is, apache is not rewriting the Location header properly. It returns a location of http://example.com/login instead of https://example.com/login.

Is there somewhere in my config where I need to tell apache to use https for the ProxyPassReverse rewrite?


Solution

  • Turns out I had improperly diagnosed this. The backend webserver (in this case, it happened to be rails) was actually specifying the http URL explicitly. This is because it was using the incoming request parameters to build its redirection URL. So, since ProxyPreserveHost was enabled, it was getting the host right, but not the protocol.

    To fix it, I added the following line to my apache config:

    RequestHeader set X-Forwarded-Proto "https"
    

    This way, the backend rails server knows that the original request was over SSL, and it generates the redirection URL properly.