Folder redirect not always working

I have just added the following rewrite rules into my .htaccess so I can move the files for my main domain into a folder but it isn’t working properly when the www. is missing off the front.

ErrorDocument 404 /notfound.html
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?felgall.com$
RewriteCond %{REQUEST_URI} !^/main/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /main/$1
RewriteCond %{HTTP_HOST} ^(www.)?felgall.com$
RewriteRule ^(/)?$ main/index.html [L]

What do I need to change to get it to redirect for both with and without the www. and preferably to also add the www. if it is missing. Currently the only pages that will display without the www. are the ones I haven’t moved yet all the rest end up on the notfound.html page (which has been moved).

Hi Stephen!

You’ve actually got TWO parts to your specification:

  1. Force www on the domain and

  2. Fetch files from the main subdirectory.

The first is simply:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^felgall\\.com [NC]
RewriteRule .? http://www.felgall.com%{REQUEST_URI} [R=301,L]

As you’re more than aware, the best way to change a website’s directory is to change the DocumentRoot, not to make redirections for every request. Okay, that was NOT the question but a reminder for other members that this should be done correctly, not via mod_rewrite.

Comments on your code:

[COLOR="DimGray"]ErrorDocument 404 /notfound.html[/COLOR]

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www[COLOR="Blue"][SIZE="3"]\\[/SIZE][/COLOR].)?felgall[COLOR="Blue"][SIZE="3"]\\[/SIZE][/COLOR].com$ [COLOR="Blue"][NC][/COLOR]
[indent][COLOR="Blue"]To ensure that the dot metacharacter only matches the dot character, escape them.  Then, because the {HTTP_HOST} is NOT case sensitive, the No Case flag SHOULD be used.  Note:  Neither of these are critical as neither would prevent the lowercase domain request from matching.[/COLOR][/indent]
RewriteCond %{REQUEST_URI} !^[COLOR="Red"]/[/COLOR]main/
[indent][COLOR="Blue"]On an Apache 2.x server, this will ALWAYS evaluate as true BECAUSE Apache 2.x will NOT match ^/.  In other words, remove the / (or change it to an optional / with ^/?).[/COLOR][/indent]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /main/$1
[indent][COLOR="Blue"]Three comments here:

1.  You don't need to capture the {REQUEST_URI} with the :kaioken: EVERYTHING :kaioken: atom because it's already available as an Apache variable.

2.  Using an absolute redirection (with the leading /) will make Apache look first at the PHYSICAL ROOT then the domain's DocumentRoot.  My advice is to remove the leading / as, with this .htaccess in the DocumentRoot, the redirection will be relative to the DocumentRoot.

3.  Finally, if you have further mod_rewrite processing, the Last flag is recommended, too.

RewriteRule .? main%{REQUEST_URI} [L]

[/COLOR]
[/indent]
RewriteCond %{HTTP_HOST} ^(www.)?felgall.com$
RewriteRule ^(/)?$ main/index.html [L]
[indent][COLOR="Blue"]If you want to specify index.html, that's fine ... but it won't be necessary with the DirectoryIndex already specifying index.html.[/COLOR][/indent]

Regards,

DK

I’d taken out the www redirect because it was breaking all the pages and not just those I’d moved so putting it back in once I fixed the rest is not a problem.

It is shared hosting so I can’t just change the root (plus I have other domains in other folders within that root folder). The code I used was what the hosting provider recommended in their knowledgebase as to how to do it - obviously they have upgraded Apache since they posted that code.

Removing the leading / appears to have fixed the problem with redirecting the folder so now with the www redirect added back it redirects all the pages correctly to the www equivalents (in the ‘main’ folder if I’ve deleted them from the root folder above it.

Getting rid of the index.html redirect and adding a DirectoryIndex statement doesn’t seem to work as I end up with the file list showing instead of the page.

So the code I have now is:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^felgall\\.com [NC]
RewriteRule .? http://www.felgall.com%{REQUEST_URI} [R=301,QSA,L]
RewriteCond %{HTTP_HOST} ^(www\\.)?felgall\\.com$
RewriteCond %{REQUEST_URI} !^main/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? main/%{REQUEST_URI} [QSA,L]
RewriteCond %{HTTP_HOST} ^(www\\.)?felgall\\.com$
RewriteRule ^(/)?$ main/index.html [QSA,L]

Obviously this can be further improved but at least it now finds all the pages - although it still adds /main after the domain name for some references from PHP calls.

Any suggestions on how to hide the /main when PHP pages call $_SERVER[‘PHP_SELF’] would be appreciated (there are too many scripts to change).

Hi Stephen!

Force (or eliminate) www is definitely NOT a problem. Because it’s a trivial thing, though, I generally put it at the head of the list in my mod_rewrite. Also, unless you WANT main/ to show (which it would with an external redirection), that is where it must be! However, as a non-problem, let’s move on to the real problem(s).

Well, actually, you would be able to change the DocumentRoot IF it were NOT the account’s main domain (i.e., if it IS an addon domain). I understand, though, that it would NOT be possible for the account’s domain.

Right! The “if I’ve deleted them from the root folder” is exactly the result of the !-f RewriteCond statement. Exactly as you need it (during a transition).

Aw, you KNOW that Options -Indexes will prevent a listing of a directory when the requested file is not found! My reason for mentioning that originally is that you do NOT want to display main/index.html which WILL happen with the external redirection. Sorry to have raced ahead with my thinking on that point.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^felgall\\.com [NC]
RewriteRule .? http://www.felgall.com%{REQUEST_URI} [R=301,QSA,L]
[indent]PERFECT - except that the QSA is the default 
action because you're not adding (or deleting) 
a query string.  MINOR point, though.[/indent]
RewriteCond %{HTTP_HOST} ^(www\\.)?felgall\\.com$
[indent]Why'd you drop the No Case flag?  Okay, more importantly 
(because you can only get to this mod_rewrite through this
domain), WHY BOTHER with this condition?[/indent]
RewriteCond %{REQUEST_URI} !^main/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? main/%{REQUEST_URI} [QSA,L]
[COLOR="DimGray"]RewriteCond %{HTTP_HOST} ^(www\\.)?felgall\\.com$
RewriteRule ^(/)?$ main/index.html [QSA,L][/COLOR]
[indent]Isn't this a repetition of the first RewriteRule in 
combination with the second - assuming, of course, 
that you have the DirectoryIndex properly set?[/indent]
[COLOR="Blue"]DirectoryIndex index.html index.php[/COLOR]
[indent]That's heirarchical so beware if you're a php programmer
and want index.php to be default, there cannot be
an index.html in those directories.[/indent]

How to hide /main? You’ll have to strip it in PHP OR use the HTML <base> tag as you would have to do if changing directory levels on your relative links. If all your relative links are still relative to the DocumentRoot of your domain, there should be NO impact at all using the <base> tag. If there are too many scripts, PHP’s autoprepend can help.

Regards,

DK

Setting DirectoryIndex index.html index.php in either the .htaccess in the root folder or the one in the main folder or both has no effect whatever on redirecting the domain name without a file name on the end into the main folder. It is in the default setup along with several other file names and does work for everything except for redirecting the domain without a filename on the end.

So while it ought to have the same effect it appears that it does not. Anyway having it there appears to work while deleting it means that the domain without a filename on the end doesn’t redirect.

I’d added the QSA because all the querystrings had disappeared. Turned out that was a result of upgrading to Opera 11 rather than moving the domain but I figured it doesn’t hurt to leave it there (or does it make a difference to efficiency?)

So based on what you have said it should now be safe for me to delete everything out of the root folder belonging to that domain apart from anything referenced by cron jobs.

Guess I’ll have to look at updating all the .php pages next to stop the main/ appearing. At least that shouldn’t take as long as the conversion I just did on the .htm files just did since there’s only about a hundred .php files and there were closer to 2000 .htm files to update (which is why I chose now to try moving the main domain into a folder alongside the add-on domains since I had changed most of the files and needed to reload them anyway - also fewer visitors over Christmas/new year means fewer people impacted if it doesn’t work).

Thanks David for reminding me about the leading slashes as that appeared to be what was causing all the problems with the .htaccess (I remembered reading about it in one of your prior posts just as soon as you mentioned it).

Hi Stephen!

Aw, DirectoryIndex can be specified on a per directory basis. It DOES affect an entire domain when in the DocumentRoot (unless modified for a specific subdirectory). Because I tend to go off on those who do NOT include the DirectoryIndex in an internal redirection, I’ll let go of this one, okay?

I can’t see any problem with leaving the QSA flag. It’s just not necessary. I can’t image more than a CPU cycle or two to read the QSA flag and decide you’re not adding/deleting so ignoring it. Not worth the effort to remove it.

Yes, that sounds reasonable. Before you do (delete all the non-cron scripts in the DocumentRoot), however, you may want to test by removing (commenting out - RewriteEngine off … RewriteEnging on) the -f and -d checks just to be sure.

THAT is the PITA associated with using a “hidden” subdirectory for the DocumentRoot files. ON THE OTHER HAND, there was a member a year and a half ago who wanted to redirect TO the new format (without main/) with a 301 then redirect internally to the servable (main/) format URI. I’ve got one version of that, one with a “marker” in the query string in the tutorial. It will soon be updated with:

I’ll let you make the substitution of main/ for index.php with the query string as it’ll be a trivial matter for you.

No problem with the leading slashes. It was one of those things I had to “bleed for” to learn (when Google-ing would have been the way to go) if you meant the ^/? bit and it was a recent “wake-up call” to read that mod_rewrite tests the PHYSICAL path before the DocumentRoot path.

Regards,

DK