Forum Moderators: phranque

Message Too Old, No Replies

htaccess simple subdomain set up for local development

subdomain .htaccess mod_rewrite relative-path virtualhost

         

rootsical

6:48 pm on Jan 17, 2011 (gmt 0)

10+ Year Member



Hi there

I am trying to set up a website, domain

examplesproject.co.uk

with a subdomain which is for the moment called

sub.examplesproject.co.uk .

I am with Bluehost and so I have set up the subdomain and I have got the same document root both for examplesproject.co.uk and sub.examplesproject.co.uk but I want content for

sub.examplesproject.co.uk

to actually be located at

examplesproject.co.uk/sub .

So why didn't I set up the document root at examplesproject.co.uk/sub for the sub-domain? Because then, in local development I would need to treat the two domains as completely separate and that would mean no relative urls which seemed silly given that the subdomain folder is just tantalisingly inside the main domain.

However, if someone browsed to sub.examplesproject.co.uk they would get the same content as examplesproject.co.uk, which I don't want, so I set up htaccess rewrite in the root folder like so:

#rewite sub-domain to sub directory
RewriteCond %{HTTP_HOST} ^[www\.]*sub.examplesproject.co.uk [NC]
RewriteCond %{REQUEST_URI} !^/sub/.*
RewriteRule ^(.*) /sub/$1 [L]


That works, however if you browse to examplesproject.co.uk/sub you can still see the content and I don't want to have two locations for the same content. However if I rewrite this sub-directory to show the sub-domain in the browser address, then I create a loop where it keeps feeding round.

As another side-point, I want my main site to be forced to use www, so I also have the following in my root htaccess..

#force add www on main domain
RewriteCond %{HTTP_HOST} ^examplesproject.co.uk$
RewriteRule ^(.*)$ http://www.examplesproject.co.uk$1 [R=301,L]


However, I want to force the sub domain not to have a www infront i.e. http://sub.examplesproject.co.uk and NOT http://www.sub.examplesproject.co.uk. To do this I am trying the following but it doesn't seem to work for other directories within the sub-domain (if that makes sense). Anyhows this is the code which I put in the sub directory (ie at examplesproject.co.uk/sub):

#force remove www on sub-domain
RewriteCond %{HTTP_HOST} ^www.sub.examplesproject.co.uk [NC]
RewriteRule ^(.*)$ http://sub.examplesproject.co.uk/$1 [L,R=301]


Thought I'd mention in case it affects things.

So, my question is, how do I achieve a nice set-up where:

1. I can use relative URLs for developing and implementing my subdomain.
2. browsing to http://sub.examplesproject.co.uk shows the content of http://www.examplesproject.co.uk/sub
3. browsing to http://www.examplesproject.co.uk/sub doesn't duplicate the sub-domain by showing the content (for SEO purposes)

and also

1. Main domain examplesproject.co.uk is forced to use www - http://www.examplesproject.co.uk.
2. Sub domain sub.examplesproject.co.uk is force NOT to use www - http://sub.examplesproject.co.uk.

If anyone can help, I would be really grateful. By the way, locally I have set up virtual hosts http://examplesproject and http://sub.examplesproject using wamp and hosts file to replicate the online behaviour.

Thanks alot for reading. Answers/suggestions welcome.

g1smd

6:56 pm on Jan 17, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I didn't have time to read all of the post, but note that [www\.]* matches
- nothing
- a single w followed by a dot,
- the pattern "w." multiple times, e.g. w.w.w.w. etc.

It can never match "www." here.

rootsical

7:26 pm on Jan 17, 2011 (gmt 0)

10+ Year Member



ok nice one so if I change it to

#rewite sub-domain to sub directory
RewriteCond %{HTTP_HOST} ^(www\.)?sub.examplesproject.co.uk [NC]
RewriteCond %{REQUEST_URI} !^/sub/.*
RewriteRule ^(.*) /sub/$1 [L]


does that make more sense? ie. with or without www. ?

jdMorgan

10:54 pm on Jan 19, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Put all of these rules, in this order, into the root .htaccess:

# Externally redirect direct client requests for test subdomain subdirectory paths to the test subdomain
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /sub/([^\ ]*)\ HTTP/
RewriteRule ^sub/(.*)$ http://sub.examplesproject\.co\.uk [R=301,L]
#
# Externally redirect all non-canonical, non-blank, non-test-subdomain hostname requests to canonical "www" main domain
RewriteCond %{HTTP_HOST} !^(www\.examplesproject\.co\.uk)?$
RewriteCond %{HTTP_HOST} !^([^.:]+\.)*sub\.([^.:]+\.)*examplesproject\.co\.uk [NC]
RewriteRule ^(.*)$ http://www.examplesproject.co.uk$1 [R=301,L]
#
# Externally redirect non-canonical subdomain hostname requests to canonical test subdomain
RewriteCond %{HTTP_HOST} ^([^.:]+\.)*sub\.([^.:]+\.)*examplesproject\.co\.uk [NC]
RewriteCond %{HTTP_HOST} !^sub\.examplesproject\.co\.uk$
RewriteRule ^(.*)$ http://sub.examplesproject.co.uk/$1 [R=301,L]
#
# Internally rewrite sub-domain requests to subdirectory path
RewriteCond %{HTTP_HOST} ^sub\.examplesproject\.co\.uk$
RewriteCond $1 !^sub/
RewriteRule ^(.*)$ /sub/$1 [L]

Checking THE_REQUEST in the now-first rule prevents the infinite redirection loop problem you encountered.

Note that exact hostnames are now enforced due to the very-careful use of case-sensitivity and anchoring.

Jim

rootsical

1:29 pm on Jan 21, 2011 (gmt 0)

10+ Year Member



wow thanks so much for looking at this. i will try it out when i get home tonight. but thanks.. at a quick glance there are some tings i don't even know about so it will be fun to decipher! thanks again..

rootsical

5:06 pm on Jan 28, 2011 (gmt 0)

10+ Year Member



OK, it seems to work.. thanks.. just wanting to decipher it a bit now as it still seems a little foreign to me..

the first section...

# Externally redirect direct client requests for test subdomain subdirectory paths to the test subdomain
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /sub/([^\ ]*)\ HTTP/
RewriteRule ^sub/(.*)$ http://sub.examplesproject\.co\.uk [R=301,L]
#


so I learnt that the rewrite condition is using a special variable %(THE_REQUEST) which refers to the first line of a http request. I didn't know but http requests are how pages are served and they are in the form METHOD URL VERSION. So usually the method is GET (but it can be HEAD, POST, DELETE etc), the url is then the address relative to the server and then the version is in the format like HTTP/1.0. so that is what you are looking at in the condition..

^marks the beginning of the condition string
[A-Z]+ is one or more uppercase letters - I guess to match POST or GET etc
\ escapes a blank space?
/sub/([^\ ]*) a request for a subdirectory - I don't understand it though. it is zero or more cause of the star and then it is a character cause of the square brackets but why another hat^? does it mean any character beginning with a space? is the backslash escaping a space?
\ escapes a blank space?
HTTP/ matches the version part of the http request ie HTTP/1.0 - you didn't need to match the actual number as you are doing a condition for a string beginning ie. the hat^ at the beginning of the condition matches anything that starts with this string

all of those http requests get redirected to the sub domain.. that bit I get, regardless of the subdirectory, so
http://www.examplesproject.co.uk/sub/directory
would end up at
http://sub.examplesproject.co.uk


am I right for the first section? thanks again

rootsical

5:22 pm on Jan 28, 2011 (gmt 0)

10+ Year Member



the second section..

# Externally redirect all non-canonical, non-blank, non-test-subdomain hostname requests to canonical "www" main domain
RewriteCond %{HTTP_HOST} !^(www\.examplesproject\.co\.uk)?$
RewriteCond %{HTTP_HOST} !^([^.:]+\.)*sub\.([^.:]+\.)*examplesproject\.co\.uk [NC]
RewriteRule ^(.*)$ http://www.examplesproject.co.uk$1 [R=301,L]
#


what does non-canonical mean?

so the condition is for the http host this time with %{HTTP_HOST},
! means NOT
^ beginning wiht
( )? zero or one of the group - why? why not just !^www\.examplesproject\.co\.uk$ I suppose you don't want zero as that is blank, is that it?
\. escapes the dot which is a special character

next condition is
! means NOT
^ beginning with
()* a group, zero or more times
inside that group... ie. [^.:]+\.
means a character that begins with any character or a colon? and which is repeated one or more times, hence the plus.
then /. escapes an actual dot
sub\. looks for the string sub.
again ([^.:]+\.)* means a group (), 0 or more times cause of the star*, inside that group is a character cause of the square brackets []. that character is one or more times cause of the plus+. it begins with (^hat) any character (unescaped dot.) or colon:? and then an escaped dot.

so not sure what these conditions are for exactly as I don't understand those groups..

in any case they get redirected to
http://www.examplesproject.co.uk
where any extra address will be appended, ie.
/holidays.html
will be appended to
http://www.examplesproject.co.uk
to end up with
http://www.examplesproject.co.uk/holidays.html
because of the $1 in the rewrite rule..

any help appreciated again. thanks..

rootsical

5:28 pm on Jan 28, 2011 (gmt 0)

10+ Year Member



third section..

#
# Externally redirect non-canonical subdomain hostname requests to canonical test subdomain
RewriteCond %{HTTP_HOST} ^([^.:]+\.)*sub\.([^.:]+\.)*examplesproject\.co\.uk [NC]
RewriteCond %{HTTP_HOST} !^sub\.examplesproject\.co\.uk$
RewriteRule ^(.*)$ http://sub.examplesproject.co.uk/$1 [R=301,L]
#


again, not sure what non-canonical means, or what canonical means..?

looking at the first condition:
%{HTTP_HOST} http host again
^ beginning with
( )* a group, zero or more times
[^.:]+\. - again I don't know what this means inside the group
sub\. the string sub. with escaped dot.
weird group again zero or more times
string examplesproject.co.uk with escaped dots

second condition..
%{HTTP_HOST} http host again
! not
^ beginning with
string sub.examplesproject.co.uk with dots escaped
$ end of condition string

rewrite rule appending to end of
http://sub.examplesproject.co.uk/$1


that right?

rootsical

5:33 pm on Jan 28, 2011 (gmt 0)

10+ Year Member



and the last section..

# Internally rewrite sub-domain requests to subdirectory path
RewriteCond %{HTTP_HOST} ^sub\.examplesproject\.co\.uk$
RewriteCond $1 !^sub/
RewriteRule ^(.*)$ /sub/$1 [L]


forst rewrite condition
%{HTTP_HOST} http host again
^ beginning with and $ ending with
string sub.examplesproject.co.uk where the dots have been escaped

second rewrite condition
i don't get what the $1 is doing here?
!^ string not begining with
string: sub/

rewrite rule
append any string ^(.*)$ to /sub/

cool, any tips would be wicked..

rootsical

5:35 pm on Jan 28, 2011 (gmt 0)

10+ Year Member



also in general just want to check I get the flags...

[NC] means upper or lower case right
[R=301] means do a 301 redirect don't just rewrite?
[L] means if you do this rule, stop doing any of the other rules.. in the htaccess file.. does this mean i need to put error file rules before theese ones with [L] to make sure that the error pages get served?

thanks again jim for all your help, you are truly helpful person thankyou

rootsical

5:38 pm on Jan 28, 2011 (gmt 0)

10+ Year Member



ah, last question.. if I wanted to add another subdomain, could I just copy the same rules and amend to suit or would the [L] flags stop it working for the second domain? sorry. thanks

g1smd

8:11 pm on Jan 28, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



/sub/([^\ ]*)
-
/sub/
followed by <anything> or <nothing> "until" the next space.

[^\ ]
- not a space
*
- zero or more times

!^(www\.example\.co\.uk)?$
- not "exactly" www.example.co.uk and "not blank". Pure HTTP/1.0 requests do not send host name in the request and without the
( )?
there would be an infinite loop.

[^.:]+\.
- NOT a "." or ":", one or more times, followed by a "." - i.e "anything" up to the next "."

Flags. Yes, you have those correct.
NC
= aNy Case.
R
= redirect (it is a 302 redirect if you don't specify 301).
L
= last.

RewriteCond $1 !^sub/
RewriteRule ^(.*)$ /sub/$1 [L]

The
(.*)
in the RewriteRule is the very first thing to be evaluated. The value is put into $1. The RewriteCond is then evaluated, matching $1 against NOT "sub/", then the RewriteRule target is processed.

    rootsical

    11:36 pm on Jan 28, 2011 (gmt 0)

    10+ Year Member



    that is fantastic.. thank you for this..

    so the hat^ in squarebrackets[] means NOT.. i get it..

    the only thing I don't understand is the $1 in the RewriteCond, in my head I don't understand how it can go backwards and re-evaluate. how can i learn more to understand it?

    but thanks for your explanations.. it's making more sense now..

    g1smd

    11:43 pm on Jan 28, 2011 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    The RewriteConds are evaluated AFTER the RewriteRule pattern is evaluated.

    $1 is populated from the (.*) in the RewriteRule. $1 is then used in the RewriteCond.

    There is no "going back". The code in .htaccess is not a "program". It is a configuration file, full of "configuration data".

    Once the RewriteConds have also been evaluated, the RewriteRule target is processed.