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 the public_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 from http://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 just http://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 from public_html/subfolder/default.html
, and the browser address bar says www.example.com
.
However, when the user clicks the 'Contact' link on that home page (coded href="/contact"
), it gets there, but shows www.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 remains www.example.com/contact/
Implementation note: In case it helps, public_html/subfolder/contact
is a folder containing a default.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 to www.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.
You can add a . htaccess file to any directory that requires lenient permissions settings (such as 760, 766, 775 or 777). You can prevent the execution of scripts inside the directory and all its sub-directories.
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 include DirectorySlash 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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With