Catch-all rewrite rule for apache that doesn't cause duplicate urls from .htaccess
You can make a catch-all rewrite rule for apache that acts somewhat like an alias, but can be implemented in a .htaccess
file while an alias can't.
As an example, assuming your document root is a hierarchy like this:
/.htaccess
/test/
/test/.htaccess
/test/file
You can "Alias" all requests to the test folder by making the root .htaccess
contain:
RewriteEngine On
RewriteRule ^(.*)$ /test/$1 [L]
And the second .htaccess
contain:
RewriteEngine On
This works great, and usually is all you need. It just has one problem - it creates multiple valid urls. Now you can access the file with both /file
and /test/file
.
Ordinarily this isn't a problem, but if you add a file called /test/test
you'll see the problem, as the fake alias stops working entirely. If the subfolder has a complex .htaccess
of its own it can cause major headaches.
Is there any way to fake an alias from a .htaccess
without the original urls still working? (Any RewriteCond
for the subfolder that would check if we've already been rewritten or not?)
... but if you add a file called
/test/test
you'll see the problem, as the fake alias stops working entirely.
Yes, the second .htaccess
file in the subdirectory prevents the URL being rewritten (since mod-rewrite is not inherited by default). You could get around this by just having the one .htaccess
file in the document root that rewrites all requests that have not already been rewritten. For example:
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) /test/$1 [L]
The REDIRECT_STATUS
environment variable is empty on the initial request and set to 200
(OK) after the first successful rewrite.
However, if you still need a .htaccess
file in the subdirectory (for other mod_rewrite directives) then you'll either need to:
repeat these directives in the subdirectories
.htaccess
file. (You then wouldn't strictly need the aboveRewriteCond
directive in the parent.htaccess
file.)Or, enable mod_rewrite inheritance. But I think you'd struggle on Apache 2.2. You would probably need something like
RewriteOptions InheritBefore
(in the subdirectories.htaccess
file), which is only available on Apache 2.4.
It just has one problem - it creates multiple valid urls.
The above method resolves this issue as well, since all requests are now rewritten (which is more like how an Apache Alias
would behave in the server config).
Otherwise, you would need to ensure that the base subdirectory was unique in order to be able to implement a canonical redirect back to the document root if the base subdirectory was accessed directly. For example:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /unique-subdir
RewriteRule (.*) /$1 [R=301,L]
THE_REQUEST
holds the first line of the initial request header and does not change when the request is rewritten.