If you are using Varnish on Port 80 and Apache on, lets say, port 88, you could run into the problem, that Apache redirects you to the Apache port, while calling a URL that is a folder.
Example:
You call http://www.example.com/test in your browser. Apache redirects you to the correct ressource under http://www.example.com:88/test/. Keep an eye on the slash at the end of the second URL.
Anyway, this behavior is not what you expect. There are several ways to resolve this issue.
The first aproach you find on several pages is, that Apache should be moved to Port 80. While Varnish is listening on this port, there is a little problem. One possible solution is, you keep Varnish on port 80 and bind it only to the external IP address of your server. Apache could listen in this way on port 80 too, but is bound to localhost (127.0.0.1) only. This is not my favorite, because debugging could become a challenge and local requests via crontab or console could become frustrating.
Another way is to configure Apache in that way, that port 80 is given right after the ServerName directive.
<VirtualHost *:88>
...
ServerName www.example.com:80
...
</VirtualHost>
This solution is not working with all Apache versions, so don’t cry when it is not your solution.
A third possibility is the Apache directive UseCanonicalName. Turning this off (which is default) uses the given host and port from the client request (http header). This makes sense, where ServerAlias is used and not a single ServerName is defined. Turning this feature on uses the ServerName. If you only have one Domain for your Host, you should stick with this setting and the given port solution from the second option above.
Finally a fourth solution involves Varnish directly. The initial request is send to port 80, so Varnish requests the ressource from Apache. With the VCL of the Varnish instance we can rewrite the result, that Apache is sending to us. The following code is working fine with Varnish 3 and could be easy adopted to Varnish 2 or 4.
sub vcl_fetch
{
...
if (beresp.status == 301 && beresp.http.location ~ ":88\/" )
{
set beresp.http.location = regsub(beresp.http.location, ":88\/", "/");
}
...
}
This way all redirects are rewritten and no longer include the Apache port. If you have a single domain ending (com, de, us, …) you can add that domain ending before the colon, to get a lower chance to run into a false substitution.