Forum Moderators: phranque
What I wish to do is map is map subdomain name to a subdirectory
subdomain.example.com --> subdomain.example.com/dir/subdomain/
where
subdomain can be any name
dir is an intermediate directory
I also wish to
1) not redirect if no hostname or subdomain = www
2) ideally trap the situation where the subdomain name entered dows not exist as a subdirectory, and redirect the user to www.example.com
3) Prevent mod_rewrite recursion
From an earlier thread that looked a very good match I found the following code. However, after playing around with it, I unfortunately did not move forward, hence this entry. Any help that can be offered will be gratefully received. I also apologies if this is old hat to you ... however to me, this is cutting edge stuff!
[webmasterworld.com...]
# Rewrite <subdomain>.example.com/<path> to example.com/<subdomain>/<path>
#
# Skip rewrite if no hostname or if subdomain is www
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST}!^www\. [NC]
# Extract (required) subdomain (%1), and first path element (%3), discard port number if present (%2)
RewriteCond %{HTTP_HOST}<>%{REQUEST_URI} ^([^.]+)\.example\.com(:80)?<>/([^/]*) [NC]
# Rewrite only when subdomain not equal to first path element (prevents mod_rewrite recursion)
RewriteCond %1<>%3!^(.*)<>\1$ [NC]
# Rewrite to /subdomain/path
RewriteRule ^(.*) /%1/$1 [L]
Welcome to WebmasterWorld!
That code will work only on servers with operating systems which support POSIX 1003.2 regular expressions, such as FreeBSD.
Without knowing how you've tested, what the results were, what errors you observed, and what errors were reported in your server error log, I can't offer any more than that, except perhaps a search [google.com] that will turn up many threads where this subject and related implementation problems have been discussed, and our forum charter [webmasterworld.com] which has links to several resources and some tips for posting here.
Jim
I am running on Fedora 2 with xampp installed. From your response it sounds like I have selected the wrong code to experiment with! If you have any specific suggestions they will be most welcomed. I have surfed considerable, and unfortuantely with only very limited experience it is difficult to sometime identify the right solution!
Regards
zimart
In addition, if the path-part "/dir" in your directory structure (stated as /dir/subdirectory above) is constant and unique, then that path-part can be used to prevent recursion; It is only necessary to have something to check in the requested URL to be sure that mod_rewrite in .htaccess has not already rewritten the requested subdomain URL to the subdirectory.
Assuming that the code goes into .htaccess, then the comments and code could be changed to something like this:
# Rewrite <subdomain>.example.com/<path> to example.com/<dir>/<subdomain>/<path>
#
# Skip rewrite if current local URL-path starts with "dir" (prevents mod_rewrite recursion)
RewriteCond %{REQUEST_URI} !^/dir/
# Skip rewrite if subdomain is www
RewriteCond %{HTTP_HOST} !^www\. [NC]
# Extract (required) subdomain (%1)
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com [NC]
# Skip rewrite if subdomain subdirectory does not exist
RewriteCond %{DOCUMENT_ROOT}/dir/%1/ [b]!-d[/b]
# Rewrite to /subdomain/path
RewriteRule ^(.*) /dir/%1/$1 [L]
Jim
[correction] Missing "!" in fourth RewriteCond. [/correction]
[edited by: jdMorgan at 9:14 pm (utc) on June 1, 2005]
I am currently experimenting with it and you have given me a great starting point which I greatly appreciate. At the moment when I type a valid subdirectory I loop (according to my access log). Everything else works great although working through other problems such as virtual domains et al has taken 3 hours and numerous beers!
When I finally solve it ... which will not be tonight I will post my solution.
One quick question, can I substitute "www." on front of the domain in the redirect example to stop the looping?
Cheers
zimart
My redirect was not as simple as I made it out to be
<subdomain>.example.com --> example.com/<dir>/<subdomain>/
however, I have a piece of php code in this directory that sets a variable and then redirects back to <subdomain>.example.com/index.php (../../index.php) which explains why I was looping as the "RewriteCond %{REQUEST_URI}!^/dir/" check to prevent looping was looking for something that did not exist.
I have tried two different solutions, both which work
1) redirect to example.com
RewriteRule ^(.*) http://example.com/dir/%1/[L]
which prevents looping as there is no subdomain now to redirect. Unfortunately this solution does not show the sub domain which I think is nice
I have also commented out "RewriteCond %{REQUEST_URI}!^/dir/" as this no longer plays a role
2) The second solution is to redirect to subdomain.example.com/index.php
RewriteRule ^(.*) /dir/%1/[L]
and have the following line to prevent recursion
RewriteCond %{REQUEST_URI}!^/index.php
This is not ideal as it shows
<subdomain>.example.com/index.php and I think index.php looks messy.
I also needed to make a change when checking if the subdomain directory existed. This now reads
RewriteCond %{REQUEST_FILENAME}/dir/%1/ -d
note no "!" required
So putting it all together my the code now looks as follows
# Rewrite <subdomain>.example.com/ to example.com/<dir>/<subdomain>/
#
# Skip rewrite if current local URL-path starts with "dir" (prevents mod_rewrite recursion)
RewriteCond %{REQUEST_URI}!^/index.php
# Skip rewrite if subdomain is www
RewriteCond %{HTTP_HOST}!^www\. [NC]
# Extract (required) subdomain (%1)
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com [NC]
# Skip rewrite if subdomain subdirectory does not exist
RewriteCond %{REQUEST_FILENAME}/dir/%1/ -d
# Rewrite to /subdomain/
RewriteRule ^(.*) /dir/%1/ [L]
so this brings me to my last wish, how can I only execute .htaccess once. Is there some other way of recognising that this code has already been executed rather than looking for a pattern.
Finally, a big thanks to you Jim, as I would not of cracked this on my own.
Cheers
zimart
The re-execution of httpd and re-execution of .htaccess after a rewrite in .htaccess is required in order to enforce access controls (security). Otherwise, it would be easy to come up with "hacks" on shared servers that could disrupt service. This is something you have to live with --or work around-- if you are limited to using .htaccess only.
Most problems are far easier to fix by using httpd.conf. Problems in .htaccess can be minimized by planning your site structure in advance with URL rewriting in mind.
I noted that you stated that your script sets a variable and "redirects." Just note that redirects should be kept to an absolute minimum, since they involve the client (browser). A redirect means that the server tells the client to "ask again" for whatever it was looking for. So, one redirect makes your site appear to be twice as slow, three makes it three times slower... Each time a client is redirected, this makes an entirely new and separate HTTP request that your server must handle.
So, when you have a choice, use "require" and "include" in php, and use internal rewrites in .htaccess instead of external redirects. The easy way to tell if you're doing a redirect is that the browser address bar changes.
Jim
Please let me know
Thanks
zimart
RewriteRule [b]^/([/b].*) /dir/%1/ [L]
Jim
One interesting area was checking to see if the directory existed. In .htaccess I had to not use "!", whereas in httpd.conf I had to use "!". Confusing ... certainly for me. Not sure if this is my environment or an apache feature.
I have not had a chance to test all options, however, once I am sure eveything is working I will post the final code.