Skip to main content

Improving Apache's canonical hostname rewrite rules

· 2 min read

According to the Apache URL rewriting guide, the way to handle Canonical Hostnames is like this:

RewriteCond %{HTTP_HOST}   !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*)$1 [L,R]

Well, those rules are not always sufficient. Specifically, what if you also owned the domain, and wished to redirect it also to the primary domain? The solution is simple - we just need to add a single $ character to the end of the match-pattern of the first RewriteCond like this:

RewriteCond %{HTTP_HOST}   !^fully\.qualified\.domain\.name$ [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*)$1 [L,R]

Now that will work nicely as long as the hosts use standard ports (ie 80 for HTTP, and 443 for HTTPS). However, some Python versions unnecessarily append the standard HTTPS port number to the Host HTTP header. Also I discovered today (after some Apache debug logging) that Adobe AIR applications have the exact same misbehavior for HTTPS, but only when running under Mac OS X.

So, to handle non-standard ports, and/or misbehaving (Python / Adobe AIR) clients, we need to extend the first match-pattern slightly to allow an optional port number, like this:

RewriteCond %{HTTP_HOST}   !^fully\.qualified\.domain\.name(:.*)?$ [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*)$1 [L,R]

So adding the 7 characters (:.*)?$ to the officially recommended Canonical Hostnames rules:

  1. redirects domains with suffixes (not just prefixes) back to the canonical host; and
  2. allows Host request headers to contain port specifiers (which is allowed by RFC2616 section 14.24).

Now I might just see if I can figure out who's responsible for the URL rewriting guide, and see I can get them to make a small addition... ;)