.htaccess rewrite to subfolder
The reason why this is happening is because of mod_dir
. It has a directive called DirectorySlash
that redirects the browser when it thinks a request is made for a directory and the trailing slash is missing to the same URI with a trailing slash appended. The problem is mod_dir and mod_rewrite get applied at different places in the URL/file mapping pipeline. So mod_rewrite mangles the URI at one point, then when mod_dir does its thing, the rewritten URI gets redirected so the URL in the browser's address bar changes to include the "hidden" internal rewrite.
You can do a couple of things here.
-
You can enforce trailing slashes yourself in mod_rewrite, so the browser gets redirected to include the trailing slash before the URI reaches mod_dir. This means all of your URLs for things like
/home
and/contact
will include a trailing slash, if one is missing, your rewrite code will redirect and add one. Something like this, above your current rule so that it gets applied first:RewriteCond %{REQUEST_URI} !^/subfolder RewriteCond %{DOCUMENT_ROOT}/subfolder%{REQUEST_URI} !-f RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
Turn off
DirectorySlash
so mod_dir stops doing this redirect. You can simply includeDirectorySlash Off
at the top of your htaccess file. However, the downside here is a possible information disclosure security issue when the trailing slash is missing.
EDIT:
In order to use the index file, without a trailing slash, you need to map to it. Try changing your rules to:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/subfolder
RewriteCond %{DOCUMENT_ROOT}/subfolder%{REQUEST_URI} -d
RewriteRule ^(.*?)/?$ /subfolder/$1/ [L]
RewriteCond %{REQUEST_URI} !^/subfolder
RewriteRule ^(.*)$ /subfolder/$1 [L]
bland328
Updated on December 28, 2020Comments
-
bland328 over 3 years
The goal:
In a virtual server on a shared Apache 2.2 box, I've attempted to configure
.htaccess
to seamlessly represent files in a subfolder of thepublic_html
folder as if they are in the root.That is, when the user accesses
http://www.example.com/home
, I need him or her to seamlessly (without rewriting the URL in the client browser) see the files fromhttp://www.example.com/subfolder/home
.My
.htaccess
file looks like this:RewriteEngine on RewriteRule !^subfolder/ subfolder%{REQUEST_URI}
The problem:
This works, but it rewrites the URL in the client browser.
That is, the user sees
http://www.example.com/subfolder/home/
in their address bar, but I need them to see justhttp://www.example.com/home
My understanding is that what I've done in
.htaccess
should result in an "internal" rewrite that's invisible to the end user, but it appears that I'm getting an "external" rewrite.What am I doing wrong?
[EDIT] Additional details:
When the user accesses
www.example.com
, it does work as desired, in that the user sees home page content served up frompublic_html/subfolder/default.html
, and the browser address bar sayswww.example.com
.However, when the user clicks the 'Contact' link on that home page (coded
href="/contact"
), it gets there, but showswww.example.com/subfolder/contact/
in the browser address bar, as if it has done a redirect instead of an internal rewrite.If I then delete the
/subfolder
text in the address bar and force a reload of the page, it works--it loads the correct content, and the address bar remainswww.example.com/contact/
Implementation note: In case it helps,
public_html/subfolder/contact
is a folder containing adefault.html
file.Another observation:
If I open a new tab and type
www.example.com/contact/
(note the trailing slash), it works as expected and desired.But if I open a new tab and type
www.example.com/contact
(no trailing slash), it redirects towww.example.com/subfolder/contact/
, which is what I don't want.I feel like that should tell me what's wrong, but the answer still eludes me.