views:

1189

answers:

8

I'm using Helicon's ISAPI Rewrite 3, which basically enables .htaccess in IIS. I need to redirect a non-www URL to the www version, i.e. example.com should redirect to www.example.com. I used the following rule from the examples but it affects subdomains:

RewriteCond %{HTTPS} (on)?
RewriteCond %{HTTP:Host} ^(?!www\.)(.+)$ [NC]
RewriteCond %{REQUEST_URI} (.+)
RewriteRule .? http(?%1s)://www.%2%3 [R=301,L]

This works for most part, but is also redirect sub.example.com to www.sub.example.com. How can I rewrite the above rule so that subdomains do not get redirected?

A: 

Can't you adjust the RewriteCond to only operate on example.com?

RewriteCond %{HTTP:Host} ^example\.com(.*) [NC]
zigdon
it should be ^example\.com$ instead. In any case I'm under the impression that chris wants a generic solution, not one for a single domain.
Vinko Vrsalovic
+2  A: 

Append the following RewriteCond:

RewriteCond %{HTTP:Host} ^[^.]+\.[a-z]{2,5}$ [NC]

That way it'll only apply the rule to nondottedsomething.uptofiveletters as you can see, subdomain.domain.com will not match the condition and thus will not be rewritten.

You can change [a-z]{2,5} for a stricter tld matching regex, as well as placing all the constraints for allowed chars in domain names (as [^.]+ is more permissive than strictly necessary).

All in all I think in this case that wouldn't be necessary.

EDIT: sadie spotted a flaw on the regex, changed the first part of it from [^.] to [^.]+

Vinko Vrsalovic
+1  A: 

I've gotten more control using urlrewriter.net, something like:

<unless header="Host" match="^www\.">
   <if url="^(https?://)[^/]*(.*)$">
     <redirect to="$1www.domain.tld$2"/>
   </if>
   <redirect url="^(.*)$" to="http://www.domain.tld$1"/&gt;
</unless>
dlamblin
A: 

Why dont you just have something like this in your vhost (of httpd) file?

ServerName: www.example.com
ServerAlias: example.com

Of course that wont re-direct, that will just carry on as normal

joshhunt
+1  A: 

Zigdon has the right idea except his regex isn't quite right. Use

^example\.com$

instead of his suggestion of:

^example\.com(.*)

Otherwise you won't just be matching example.com, you'll be matching things like example.comcast.net, example.com.au, etc.

A: 

@Vinko - are you saying I should replace line 2 with your condition, or add your condition on a new line? Will adding it on a new line affect the RewriteRule using the %1, %2, and %3?

chrisofspades
+1  A: 

@Vinko

For your generic approach, I'm not sure why you chose to limit the length of the TLD in your regex? It's not very future-proof, and I'm unsure what benefit it's providing? It's actually not even "now-proof" because there's at least one 6-character TLD out there (.museum) which won't be matched.

It seems unnecessary to me to do this. Couldn't you just do ^[^.]+\.[^.]\+$? (note: the question-mark is part of the sentence, not the regex!)

All that aside, there is a bigger problem with this approach that is: it will fail for domains that aren't directly beneath the TLD. This is domains in Australia, UK, Japan, and many other countries, who have hierarchies: .co.jp, .co.uk, .com.au, and so on.

Whether or not that is of any concern to the OP, I don't know but it's something to be aware of if you're after a "fix all" answer.

The OP hasn't yet made it clear whether he wants a generic solution or a solution for a single (or small group) of known domains. If it's the latter, see my other note about using Zigdon's approach. If it's the former, then proceed with Vinko's approach taking into account the information in this post.

Edit: One thing I've left out until now, which may or may not be an option for you business-wise, is to go the other way. All our sites redirect http://www.domain.com to http://domain.com. The folks at http://no-www.org make a pretty good case (IMHO) for this being the "right" way to do it, but it's still certainly just a matter of preference. One thing is for sure though, it's far easier to write a generic rule for that kind of redirection than this one.

+1  A: 

@org 0100h Yes, there are many variables left out of the description of the problem, and all your points are valid ones and should be addressed in the event of an actual implementation. There are both pros and cons to your proposed regex. On the one hand it's easier and future proof, on the other, do you really want to match example.foobar if sent in the Host header? There might be some edge cases when you'll end up redirecting to the wrong domain. A thrid alternative is modifying the regex to use a list of the actual domains, if more than one, like

RewriteCond %{HTTP:Host} (example.com|example.net|example.org) [NC]

(Note to chris, that one will change %1)

@chrisofspades It's not meant to replace it, your condition number two ensures that it doesn't have www, whereas mine doesn't. It won't change the values of %1, %2, %3 because it doesn't store the matches (iow, it doesn't use parentheses).

Vinko Vrsalovic