Yesterday I was trying to deploy Varnish cache in front of my app server and was faced with the issue of infinite redirect loop for some pages. This problem happened when I tried to use HTTPS for pages which are not supposed to be.
The problem is like this:
I am terminating SSL at the ELB, behind that is the Varnish and behind that is the app server. Its a standard practice that whenever we hit the app server with HTTPS scheme for a page which is not supposed to be HTTPS it throws a 302 with the same page url , only difference being HTTP instead of HTTPS.
With SSL termination at ELB we can get the original scheme using a header which ELB sets called X-Forwarded-Proto . So my app was making use of this and doing a redirection from HTTPS -> HTTP. Everything was good.
The only problem was the Varnish cache caching 302. So this is what happened:
1) User hit https://example.com/myurl.
2) Varnish sends request to the backend.
3) Backend send a 302 redirect to http://example.com/myurl.
4) The response (302) gets cached in varnish
Now the problem is since scheme is not a part of the varnish hash key so effectively the mapping inside varnish is:
myurl : 302 irrespective of the scheme (https/http). So from now even if the user hit http://example.com/myurl he would always get a 302 to the same url. Infinite redirect loop.
Solution is very simple just make scheme part of the vcl_hash like this:
sub vcl_hash {
hash_data(req.url);
hash_data(req.http.X- Forwarded-Proto);
return(hash);
}
Here scheme (X-Forwarded-Proto) has been made a part of the key. So the internal mapping in varnish would like like:
myurl_http : Actual content
myurl:https: 302 redirect
Problem solved.
If you are facing infinite redirect loop for naked domain redirects (example.com -> www.example.com) or otherwise, read this.
The problem is like this:
I am terminating SSL at the ELB, behind that is the Varnish and behind that is the app server. Its a standard practice that whenever we hit the app server with HTTPS scheme for a page which is not supposed to be HTTPS it throws a 302 with the same page url , only difference being HTTP instead of HTTPS.
With SSL termination at ELB we can get the original scheme using a header which ELB sets called X-Forwarded-Proto . So my app was making use of this and doing a redirection from HTTPS -> HTTP. Everything was good.
The only problem was the Varnish cache caching 302. So this is what happened:
1) User hit https://example.com/myurl.
2) Varnish sends request to the backend.
3) Backend send a 302 redirect to http://example.com/myurl.
4) The response (302) gets cached in varnish
Now the problem is since scheme is not a part of the varnish hash key so effectively the mapping inside varnish is:
myurl : 302 irrespective of the scheme (https/http). So from now even if the user hit http://example.com/myurl he would always get a 302 to the same url. Infinite redirect loop.
Solution is very simple just make scheme part of the vcl_hash like this:
sub vcl_hash {
hash_data(req.url);
hash_data(req.http.X-
return(hash);
}
Here scheme (X-Forwarded-Proto) has been made a part of the key. So the internal mapping in varnish would like like:
myurl_http : Actual content
myurl:https: 302 redirect
Problem solved.
If you are facing infinite redirect loop for naked domain redirects (example.com -> www.example.com) or otherwise, read this.