http in the Location-header when the original request was made over https

I am currently implementing https on our production environment, but I am scratching my head over a little thing here.

SSL is terminated in the load balancer and the flow in our stack is basically like this:

Production: Browser <- https -> Load balancer <- http -> Apache <- http -> Load balancer <- http -> Tomcat

Testing: Browser <- https -> nginx <- http -> Load balancer <- http -> Tomcat

When I access our login-page over HTTPS:

Request headers

POST /login/form HTTP/1.1
Host: www.example.org
Connection: keep-alive
Content-Length: 74
Cache-Control: max-age=0
Origin: https://www.example.org
Content-Type: application/x-www-form-urlencoded
Referer: https://www.example.org/login
Accept-Encoding: gzip,deflate,sdch
Accept-Language: nb,en-US;q=0.8,en;q=0.6

Response headers

HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Fri, 17 Jan 2014 11:16:50 GMT
Content-Length: 0
Connection: keep-alive
Set-Cookie: FOO=example
Location: http://www.example.org/portal
Strict-Transport-Security: max-age=31536000

I talked to a developer and he told me the following:

In the code there is sth like request.sendRedirect("/portal") and Tomcat does the rest.

I am able to reproduce the problem on the testing environment, although a bit different stack.

My questions:

  1. Why do I get http as the scheme in the Location-header when the original request from the browser was made with https?
  2. Is this an Apache mod_rewrite/mod_proxy or nginx problem?
  3. Is this a problem with Tomcat?

You get http in the response headers because the request that reaches Apache is HTTP - the SSL has been stripped away at the load balancer. So from what Apache sees, it's just an HTTP request.

You can work around this by setting

ServerName https://www.example.org

in the global or virtual host configuration. This will override the default http scheme so Apache will send the response you want. The documentation for ServerName mentions this.


I had a similar issue. Adding the following in your virtualhost config should solve the problem. Basically it would edit the http request to https

Header edit Location ^http://(.*)$ https://$1