htaccess – Redirect to subfolder without changing browser URL

Sorry, just realised what is happening. It has nothing to do with the second .htaccess file in the subdirectory, as mentioned in comments.

RewriteRule ^.*$ subfolder/public [NC,L]

Since public is a physical directory on the file system, you need to include a trailing slash when internally rewriting to that directory. Otherwise, mod_dir is going to try to “fix” the URL by appending a slash – that is where the external redirect is coming from. (mod_dir implicitly triggers an external redirect from subfolder/public to subfolder/public/.)

So, try the following instead in your root .htaccess file:

RewriteRule .* subfolder/public/ [L]

The important thing is the trailing slash. The anchors (^ and $) on the RewriteRule pattern are not required, since you are matching everything. And the NC flag is also not required for the same reason.

As always, make sure the browser cache is clear before testing.


UPDATE#1: The single directive above rewrites everything, including static resources, to the directory subfolder/public/ which then relies on the second .htaccess file in the subdirectory to correctly route the request. In order to allow static resources to be rewritten correctly (represented in the HTML as root-relative URL-paths, of the form "/js/myjs.js") then you will need additional directives in order to rewrite these.

For example, to specifically rewrite all .js and .css files to the real location in /subfolder/public/...

# Rewrite static resources
RewriteRule (.+\.(?:js|css))$ subfolder/public/$1 [L]

# Rewrite everything else to the "public" directory
RewriteRule .* subfolder/public/ [L]

UPDATE#2: To make the above more general, and to rewrite any static resource (images, PDFs, .txt, etc…) we can check for the existence of the file before rewriting, something like:

# Rewrite static resources
RewriteCond %{DOCUMENT_ROOT}/subfolder/public/$1 -f
RewriteRule (.+) subfolder/public/$1 [L]

# Rewrite everything else to the "public" directory
RewriteRule .* subfolder/public/ [L]

This will mean that if any .css does not exist it will be passed through to subfolder/public/.

Leave a Comment