Forum Moderators: phranque

Message Too Old, No Replies

htaccess dynamic subdomain

         

newmie

2:40 pm on May 24, 2010 (gmt 0)

10+ Year Member



Hello,

I'm trying to create multiple subdomains with .htaccess. I have created the appropriate entries in DNS and httpd.conf (ServerAlias *.domain.com).

My question is: if the requested file or directory exists within the subdomain directory, serve it up, otherwise [pass] the url arguments to the GLOBAL index.php file.

For instance:

www.domain.com -> /www/
sub1.domain.com -> /www/_sites/sub1

If the requested resource is a file or directory in the subdomain (i.e., sub1.domain.com/css/main.css) it would be served, but if it's not, it gets delegated to www.domain.com/index.php?uri=$1.

Here's my htaccess as it stands, and I'm (obviously) using mod_rewrite:


RewriteEngine On
RewriteBase /

RewriteCond %{HTTP_HOST} !^(www\.)?domain.com [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.domain.com [NC]
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.*) /_sites/%1/$1 [L,QSA]

RewriteCond %{HTTP_HOST} !^(www\.)?domain.com [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.domain.com [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php?uri=$1 [L,QSA]


any help at all would be appreciated. Thanks so much for any replies!

Currently, I get the following 500 error: mod_rewrite: maximum number of internal redirects reached. Assuming configuration error.

[edited by: jdMorgan at 5:03 pm (utc) on May 24, 2010]
[edit reason] Minor edit to clarify (added missing word). [/edit]

jdMorgan

4:59 pm on May 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Bear in mind that a file or directory does not "exist or not exist" in a subdomain. It "exists or does not exist" in the server filesytem. Therefore, you have to include the "_sites/%1" path in the filepaths to be checked.

Since %{REQUEST_FILENAME} will not include this additional path information, you have to "construct" the proper filepath to be tested.

Doing that, correcting three logic errors (a missing [OR] flag and a potential infinite loop in each rule), and simplifying the code for best performance, you'd get something like this:

RewriteEngine on
RewriteBase /
#
RewriteCond $1 !^_sites/
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com [NC]
RewriteCond %{DOCUMENT_ROOT}/_sites/%1/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/_sites/%1/$1 -d
RewriteRule ^(.*)$ /_sites/%1/$1 [L]
#
RewriteCond $1 !^(index\.php$|_sites/)
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.example.com [NC]
RewriteRule ^(.*)$ /index.php?uri=$1 [QSA,L]

The original first RewriteCond was somewhat redundant because both the first and second RewriteConds must match to invoke the rule. So I also simplified it. In other words, a request for just "example.com" with no subdomain will not match the second rule, so no provision is needed for a missing "www." in the first RewriteCond.

Note that the second rule can now never be invoked if the first rule has already been invoked. So checking for -f -d in the second rule is no longer necessary.

Since nothing is appended to the existing query string in the first rule, [QSA] is not needed.

Note also the addition of "loop prevention" RewriteConds to both rules.

Be careful here... This code allows and will rewrite requests for uppercase and mixed-case subdomains. With these rules in place, Apache will treat lowercase, uppercase, and mixed case subdomain requests as requests separate subdirectories, and upper- and mixed-case subdomain requests *will not* exist (unless you create them.) Therefore upper- and mixed-case requests will not invoke the first rule.

You may wish to add another rule to handle mis-cased subdomain requests, and exclude them from these first two rules by dropping the [NC] on the second RewriteCond in each rule, and checking for a subdomain matching "([a-z0-9]([a-z0-9\-]*[a-z0-9])?)" instead of just "([^.]+)" to improve efficiency (exists-checks are very CPU intensive, since they are calls to the OS to go check the filesystem). Therefore exists-checks should be avoided whenever possible, and should always be done last after any other RewriteConds.

Also, consider what you might want to with requests for "www.<subdomain>.example.com" or "<subdomain>.www.example.com" With the current code, those cases are not handled.

And finally, also consider what you might want to do with direct client requests for www.example.com/_sites/<subdomain>/<whatever> -- As it stands now, those would be duplicate URLs fo <subdomain>.example.com/<whatever>. I would suggest adding a rule to 301-redirect those requests to the correct subdomain-URL format. It's a bit tricky, so this should be left until all other issues cited above are decided and resolved...

Jim

jdMorgan

5:05 pm on May 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



A further consideration: Do you really want to rewrite all requests for www.example.com images, CSS files, JavaScript files, etc. to your script? If not, exclude them by filetype, and not by "exists" if at all possible...

Jim