Apache’s mod_rewrite is an awesome module providing all sorts of impressive capabilities, however it’s sometimes overkill when all you want is to redirect an entire site or path to a different one. In these situations, the mod_alias’s Rewrite function is often the ideal solution, with it’s simple syntax.
Redirect permanent / http://newhost.example.com/ Redirect permanent /test.html http://newhost.example.com/test.php
Unfortunately I’ve found a situation where certain syntax can cause failures in some environments – consider the following:
Redirect permanent / http://newhost.example.com
This example will work happily when a user is accessing Apache directly, however it will fail horribly when accessing via a Varnish cache, eg:
$ wget oldhost.example.com --2012-11-27 11:26:54-- http://oldhost.example.com/ Resolving oldhost.example.com (oldhost.example.com)... 172.16.1.1 Connecting to oldhost.example.com (oldhost.example.com)|172.16.1.1|:80... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: unspecified ERROR: Redirection (301) without location.
This was the source of a lot of headaches since the site still *worked* correctly when connecting directly to it, but kept failing whenever accessed via the varnish caches.
The cause is simply a missing trailing / in the redirect – configuration should actually look like:
Redirect permanent / http://newhost.example.com/
It’s a nasty trap for the unwary sysadmin, since it works perfectly when accessing the server directly – I’m not entirely sure whether it’s an issue with Apache allowing this syntax, or whether it’s an issue with Varnish not understanding how to proceed – maybe a bit of both.
RFC 2616 isn’t clear, it states that if the abs_path is empty, it’s the same as abs_path being equal to /, and that when requesting a URL with an undefined abs_path, it should be treated as /… but it doesn’t clarify whether an application serving a URL should or shouldn’t append the trailing /.
I guess ideally Apache should be patched to serve up URLs with a trailing / and Varnish should accept redirects with or without it to protect both applications from blame.