Forum Moderators: phranque

Message Too Old, No Replies

Mapping subdomain.example.com to subdomain.example.com/dir/subdomain

         

zimart

10:23 pm on May 31, 2005 (gmt 0)

10+ Year Member



I have a simple problem, however, after spending hours surfing, it is still a problem that baffles me!

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]

jdMorgan

11:40 pm on May 31, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



zimart,

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

zimart

6:39 am on Jun 1, 2005 (gmt 0)

10+ Year Member



Hi Jim
Thanks for your response

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

jdMorgan

2:51 pm on Jun 1, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The function of the POSIX-1003.2-dependent part of that code is to prevent recursion. This is only a problem in .htaccess -- in httpd.conf, there's usually no recursion problem.

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]

The line above that checks for 'subdomain-subdirectory exists' may need some adjustment to work on your server. If the code deson't work as shown, then comment-out that line. A simple redirect can be used to find the correct form by doing a few tests if that line doesn't work.

Jim

[correction] Missing "!" in fourth RewriteCond. [/correction]

[edited by: jdMorgan at 9:14 pm (utc) on June 1, 2005]

zimart

8:53 pm on Jun 1, 2005 (gmt 0)

10+ Year Member



Jim
Thanks for the example

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

jdMorgan

9:15 pm on Jun 1, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



No. This is an internal rewrite, so "www" doesn't enter into it.

There was also a typo in my code. In the 4th RewriteCond, the "!" was missing.

I have corrected it above, and noted the change for members who read this thread later.

Jim

zimart

8:43 pm on Jun 2, 2005 (gmt 0)

10+ Year Member



Not quite sure where i start, however, I have got it working, albeit with one wish out standing.

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

jdMorgan

10:44 pm on Jun 2, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> 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.

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

zimart

6:40 am on Jun 3, 2005 (gmt 0)

10+ Year Member



Hi Jim
From your last reply, am I right in assuming that I could move this code to my httpd.conf (virtualhost section). And by doing so, this code would only be executed once, solving my problem of checking for recursion, and also better from a performance prospective.

Please let me know

Thanks
zimart

jdMorgan

3:29 pm on Jun 3, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes. Be aware that you will need to restart your server after any change to the code in httpd.conf, and that the RewriteRule will need a small change -- the addition of a leading slash -- to work in httpd.conf.

RewriteRule [b]^/([/b].*) /dir/%1/ [L]

Also, please re-read message #6 above. It appears that the code you posted in message #7 does not contain the correction I made. You should not be having recursion problems if you made that change.

Jim

zimart

10:30 pm on Jun 3, 2005 (gmt 0)

10+ Year Member



I have now converted to httpd.conf

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.

jdMorgan

3:50 am on Jun 4, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Just FYI, "!" means NOT - The logical complement operator. So -d means "exists as a directory" while!-d means "does not exist as a directory."

The documentation cited in our charter may be helpful in decoding all the ^hats, dollar$, and exclamation points!

Jim