Forum Moderators: phranque

Message Too Old, No Replies

Another .htaccess redirect question

         

freshjerky

4:43 am on Jan 14, 2004 (gmt 0)

10+ Year Member



I have been reading through the forums on this site and have to say that the information here is fantastic. I'm happy to now be a part of it.

I have a problem that I have been working on for awhile now and cannot seem to get straight. Hopefully, someone here might be able to help out.

I am simply trying to redirect url requests to subdirectories dependent on the requested domain. It is sort of a pseudo virtual hosting under a single user account since I don't have access to httpd.conf on this server.

Here is my .htaccess file:

RewriteEngine on
RewriteRule ^(.*) /%{HTTP_HOST}/$1 [L]

This works exactly as it should to redirect a request for [domain.com...] to [domain.com...] while displaying the url in the browser simply as [domain.com....]

As a side note, it was necessary for me to add another .htaccess file in each domain's subdirectory to turn the RewriteEngine off to avoid the infinite loops that occur.

My problem is that I cannot browse directly to any subdirectories of the domain itself. For example, if I try to go to [domain.com...] I get a "forbidden" page.

I am not sure if it is looking for testdir at the root of the site and ignoring the .htaccess file or if it is looking inside the domain.com subdirectory and, perhaps, is being shutdown by the .htaccess file I put in the subdirectory?

Any help is greatly appreciated.

jdMorgan

8:39 am on Jan 14, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



freshjerky,

Welcome to WebmasterWorld [webmasterworld.com]!

With your posted rule, a request for http://domain.com/testdir will be redirected to http://domain.com/domain.com/testdir

You could stop the "infinite looping" you describe by several means, some possibly simpler and less restrictive that giving up mod_rewrite capability in each subdirectory.

First, you could make a list of subdomain/subdirectories, and exclude those from the rule:


RewriteEngine on
RewriteCond %{REQUEST_URI} !^/subdomain1
RewriteCond %{REQUEST_URI} !^/subdomain2
RewriteCond %{REQUEST_URI} !^/subdomain3
RewriteRule ^(.*) /%{HTTP_HOST}/$1 [L]

This works well for a small number of subdomains, but gets unwieldy for hundreds of subdomains.

Aside: To save you some time, the following doesn't work:

RewriteCond %{REQUEST_URI}!^%{HTTP_HOST} 

I tried that myself last year, trying to save code while implementing "test" and "production" subdomains... :(

Another way to do it would be to bypass the rule. This only works if this code is placed as the last mod_rewrite section in your .htaccess file:


RewriteEngine on
RewriteCond %{REQUEST_URI} ^/(subdomain1¦subdomain2¦subdomain3)
RewriteRule .* - [L]
RewriteRule ^(.*) /%{HTTP_HOST}/$1 [L]

This is similar in concept to the first example -- you have to list the subdomains. The first RewriteRule will make the RewriteEngine "quit" due to the [L] flag if the RewriteCond and the RewriteRule match. The URL is not changed because of the special "-" substitution string. If that fails, then the second RewriteRule will modify the URL and exit.

There are many variations on the above method. The following method may be easier:


RewriteCond %{REQUEST_URI} !^/subs
RewriteRule (.*) /subs/%{HTTP_HOST}/$1 [L]

This simply requires a "change of plans" to put all of your subdomain/subdirectories under a master subdirectory called "subs". You can then use that master subdirectory name as an exclusion in order to stop the rewrite looping problem. It also has the possible added benefit of keeping things organized in your web root directory.

I haven't yet found a slick way to use a variable in the pattern of a RewriteCond or RewriteRule -- mod_rewrite's just not designed that way. A free beer for the first to tell me (deliverable in N. Texas).

Anyway, it's too late for me to be doing any more intense technical stuff, so I hope that helps you out.

Jim

freshjerky

10:23 am on Jan 14, 2004 (gmt 0)

10+ Year Member



Thank you very much for your thorough reply.

First off, I like your suggestion of the subs/ directory, so I have implemented it. I believe that it should help keep things organized a bit better.

I changed the .htaccess as you suggested:

RewriteCond %{REQUEST_URI}!^/subs 
RewriteRule (.*) /subs/%{HTTP_HOST}/$1 [L]

and I removed the .htaccess files in the subdirectories, but it seems to be behaving in the same manner. It correctly redirects to the root of the domain, but won't let me enter the subdirectories.

I cannot go to domain.com/testdir, but I can browse directly to domain.com/subs/domain.com/testdir.

Thanks again for your help.

jdMorgan

5:44 pm on Jan 14, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



freshjerky,

Well, that is strange... Let me ask a couple of questions - really related to each other...

Do you redirect all requests to www.domain.com to domain.com or vice-versa before applying the above rules?
Do you redirect all uppercase and mixed-case domain requests to the all-lowercase domain before applying the rule?

The reason I'm asking is that/subs/domain.com/testdir/ and /subs/www.domain.com/testdir/ will be two different subdirectories, and on *nix, each capitalization variant will also be a separate subdirectory unless you take steps to "standardize" the requested domain names before you look up their subdirectories.

Another tip I should mention is that when doing rewrites like this, it is critical to flush your browser cache before each new version is tested - otherwise, your browser may cache the previous 404 response, leading you to believe that nothing has changed!

BTW, I think it's a very good idea to mark all test pages and error responses as non-cacheable using mod_headers while testing rewrites of this nature, and even for normal operation, leaving the expiry time short on error pages. This minimizes the possibility of affecting a user who caches a faulty response while you are testing and the function of your site is what I like to call "non-optimal." :)

A quick way to fool caches if you are testing on a static site is to append a query string to the URL, such as "?1143" (the current time). This means nothing to the server on a static site, but will make each request unique, and avoid cache-related side-effects.

One more suggestion: Since you've already got the loop-prevention in place, you can test this as an external redirect to see where it thinks it is going, and then change it back to an internal rewrite once all the bugs are worked out.

Jim

freshjerky

8:37 pm on Jan 14, 2004 (gmt 0)

10+ Year Member



Thanks again for your reply.

Do you redirect all requests to www.domain.com to domain.com or vice-versa before applying the above rules?

Basically, the setup I have right now is to have www.domain.com as a symlink of domain.com. So, the directory structure looks like this:

drwxr-sr-x domain.com
lrwxrwxrwx www.domain.com -> domain.com

Do you redirect all uppercase and mixed-case domain requests to the all-lowercase domain before applying the rule?

I haven't done anything to alter this. However, I believe that something is in place server-side, because if I make a request for one of my domains in all caps or in mixed cases, the browser address will first be converted to lowercase before redirecting.

--
I will follow your suggestions for these test pages. Be assured that I have been clearing the cache, though.

I am not positive about what you are getting at when you say that I should do an "external" redirect. But, I believe it has to do with adding the [R]:

RewriteEngine on
RewriteCond %{REQUEST_URI}!^/subs
RewriteRule (.*) /subs/%{HTTP_HOST}/$1 [R,L]

Even if not, doing the above has shown me something. When I put [domain.com...] in my browser, it now redirects to [domain.com...] However, if I put [domain.com...] in my browser, no redirection occurs and I get the "forbidden" page.

This is what has been driving me crazy. All of the reading and research that I have done on this lastly states that this *should* be working. I must be missing something here. Could there be something server-side that is affecting this?

jdMorgan

7:53 pm on Jan 15, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> Could there be something server-side that is affecting this?

Well technically, all of this mod_rewrite stuff is server-side, but yes, there may be a directive in a higher-level http.conf or .htaccess file that is grabbing the request and changing it before you get it, thus interfering with your code's expected behaviour.

A simple way test this would be to comment out your RewriteEngine on directive, thus disabling all of your code, and then request that particular path again and see what happens.

<added>
External redirect for testing:


RewriteEngine on
RewriteCond %{REQUEST_URI}!^/subs
RewriteRule (.*) http://%{HTTP_HOST}/subs/%{HTTP_HOST}/$1 [R,L]

You may also need Options +FollowSymLinks at the top, if this option is not enabled at a higher level.
</added>

Jim