...does not work when running on a temporary URL like http://example.com/~test/
The "problem" in this instance really stems from using (what appears to be) an "Apache per-user web directory". If /~test
was a physical subdirectory then you would not need to explicitly set the RewriteBase
, as the directory-preifx (the absolute filesystem path to the location of the .htaccess
file) would be "correct". The issue here is that /~test
does not relate directly to a physical subdirectory - it is a URL-path (as opposed to a filesystem path) and is essentially an alias to another part of the filesystem - and therefore is different to the directory-prefix.
By default, a relative substituion string in the RewriteRule
directive is relative to the filesystem (the directory-prefix). But when using an Apache per-user web directory or Alias
, it now needs to be relative to the URL-path. This is when the RewriteBase
directive is required*1 - it enables relative substitution strings to be relative to the stated root-relative URL-path (as opposed to the default absolute filesystem path).
*1 Or, this can be calculated using a method as mentioned in @FitzPatrick's answer. This sets an environment variable that must be explicitly used in each substitution string as required. For example:
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule (.*) - [E=BASE:%1]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) %{ENV:BASE}/index.php [L]
But note that this does not behave quite the same as when using RewriteBase
. When using RewriteBase
, the URL-path is only prefixed at the very end of the rewriting process. This can be an important factor if you have rules that are expected to chain together. (And this also behaves differently to when no URL-path prefix is specified at all.)
Aside: "Temporary" per-user web directories can cause other issues with root-relative URLs in client-side development. Unless these are factored into account on the development server then root-relative URLs are going to be different between servers.