234

I have a website that doesn't seem to redirect from non-www to www.

My Apache configuration is as follows:

RewriteEngine On
### re-direct to www
RewriteCond %{http_host} !^www.example.com [nc]
RewriteRule ^(.*)$ http://www.example.com/$1 [r=301,nc] 

What am I missing?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
user121196
  • 30,032
  • 57
  • 148
  • 198
  • 1
    For a `.htaccess` based solution I suggest an answer that has been posed on the diametral question: http://stackoverflow.com/a/5262044/367456 – hakre Feb 14 '14 at 07:54
  • this is good, it does add a slash to the url though, so lose the slash before the dollar. – wuxmedia Sep 16 '19 at 09:08
  • Possible duplicate of [Generic htaccess redirect www to non-www](https://stackoverflow.com/questions/234723/generic-htaccess-redirect-www-to-non-www) – Bobík Oct 20 '19 at 13:38

26 Answers26

558

Using the rewrite engine is a pretty heavyweight way to solve this problem. Here is a simpler solution:

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / http://www.example.com/
</VirtualHost>

<VirtualHost *:80>
    ServerName www.example.com
    # real server configuration
</VirtualHost>

And then you'll have another <VirtualHost> section with ServerName www.example.com for your real server configuration. Apache automatically preserves anything after the / when using the Redirect directive, which is a common misconception about why this method won't work (when in fact it does).

maciek
  • 3,198
  • 2
  • 26
  • 33
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 26
    How do you do it for a site that has an ssl virtual host as well? – Shabbyrobe Dec 11 '10 at 16:16
  • 29
    I get the error "The webpage at example.com has resulted in too many redirects" when using this suggestion. Do others have this problem? – Jonathan Berger Mar 28 '11 at 19:38
  • Gosh you rock, and so does Duck Duck Go for showing this at the top. Google fail :/ – mdgrech Jan 13 '12 at 03:44
  • 1
    I found this page first, using Google. Thanks for the answer, it's a really easy and efficient way to do it. – VladFr Jan 21 '12 at 11:31
  • 1
    @Greg Hewgill Can you provide similar solution for redirecting from www to now-www please? – DivinesLight Feb 12 '12 at 21:06
  • 4
    @BlackDivine: There's nothing magical about doing it in the other direction. Simply swap `www.example` and `example` wherever they appear in the sample. – Greg Hewgill Feb 12 '12 at 21:17
  • @Shabbyrobe I would assume: ``` ServerName example.com Redirect permanent / https://www.example.com/ ``` – Boy Baukema Jan 08 '13 at 12:59
  • Does it make sense to put example.com besides www.example.com into the hosts file for faster resolution? – Nick Russler Mar 28 '13 at 13:15
  • 11
    @JonathanBerger If you too many redirects, then you have probably not configured well the file. Make sure to have 2 VirtualHosts: one with non-www which is the above and the other with ServerName www.example.com which has the real configuration. Also make sure to have not a redirect in www.example.com configuration as well (both mod_alias and mod_rewrite). – Savas Vedova Aug 04 '13 at 08:03
  • 3
    For a virtual host server, say example.com, I have `Redirect 301 / http://example2.com/extra/` but when it redirects, it misses the trailing slash, meaning that `example.com/blah` goes to `example2.com/extrablah`. Any ideas? (Apache 2.2.22) – Peter Howe Jan 08 '14 at 16:45
  • 2
    @Peter Howe: the `VirtualHost` block with ServerName set to example.com and containing the redirect should come after the one with the www.example.com domain name to avoid that. – tirdadc May 28 '14 at 23:19
  • 1
    For SSL, you may refer to [https://wiki.apache.org/httpd/RedirectSSL](https://wiki.apache.org/httpd/RedirectSSL). – hotohoto Mar 05 '15 at 01:17
  • Why use when a simple If/Redirect in your .htaccess file will suffice? (as per http://httpd.apache.org/docs/current/rewrite/avoid.html#setenv) – André Chalella May 07 '15 at 20:35
  • Never mind, I think I know: in a domestic server for one domain only it wouldn't make a difference, but in a web server for millions of pages the default host won't point to your `DocumentRoot`, right? – André Chalella May 07 '15 at 20:51
  • @AndréNeves by the way, for server speed it would be better to do away with all `.htaccess` files completely and keep all apache directives in configuration files instead. Here's an explanation of how demanding AllowOverride is (https://servercheck.in/blog/3-small-tweaks-make-apache-fly). – Buttle Butkus Jul 02 '15 at 05:52
  • @ButtleButkus yeah, not viable for web hosting, though. – André Chalella Jul 02 '15 at 06:05
  • So this is a solution only for ppl having access to the server files right? Because I can't just put it in the .htaccess file. – AlexioVay Dec 08 '16 at 11:09
  • The disadvantage of this is that it requires two virtualhosts, whereas using mod_rewrite only requires the one. – kloddant Mar 30 '17 at 18:18
  • Solution works but when using custom Access and Error logs they will need to be set inside both Virtual Hosts or else Apache will be keeping logs for the non-www (or the www depending on your setup) version of the site at the '/var/log/apache2/other_vhosts_access.log' file – consuela Aug 19 '17 at 14:24
  • Great solution as long as you have access to the virtual host configuration. Not useful for most shared hosting environments, unfortunately. – Cobus Kruger Sep 05 '17 at 07:01
  • very cool. I'd add the *443 config...I had to do both :) Thanks for this – Sampgun Mar 11 '18 at 12:40
  • ServerName example.co.in Redirect 301 / http://www.example.co.in/ ServerName www.example.co.in #ServerAlias www.example.co.in DocumentRoot /var/www/html/example Options -Indexes Order allow,deny Allow from all It is giving error : ERR_TOO_MANY_REDIRECTS. Please help where I did mistake. – Sumit Raghav Apr 09 '18 at 07:45
  • @tirdadc thanks for that comment about the ordering of virtual hosts. Is there any documentation about that?! – Jasper Jul 29 '18 at 12:33
  • How can i redirect permanently https://example.com to https://www.example.com @GregHewgill – khurshed alam Sep 25 '18 at 10:42
  • How do you reverse it? Apparently changing the document doesn't change the redirect – jDave1984 Jan 18 '19 at 18:19
114

http://example.com/subdir/?lold=13666 => http://www.example.com/subdir/?lold=13666

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Ivar
  • 6,138
  • 12
  • 49
  • 61
burzumko
  • 1,141
  • 1
  • 7
  • 2
  • 4
    Oh that's neat, this can be included in the server config at the top level (and if so) will apply to every virtual host! – thenickdude Aug 19 '14 at 23:02
  • Hello @burzumko how do you achieve this, which is true for all without www, but then let, say `example.com/subdi1/ws/* ` go through without www ? – black sensei Mar 18 '15 at 13:08
  • 2
    I used this solution for HTTPS virtual hosts too. Just add an `s` to http in the third row. – rodrigoap Sep 12 '17 at 18:10
56
<VirtualHost *:80>
    ServerAlias example.com
    RedirectMatch permanent ^/(.*) http://www.example.com/$1
</VirtualHost>
cherouvim
  • 31,725
  • 15
  • 104
  • 153
  • This didn't work for me; it caused an infinite redirect loop to the same site – dmiller309 May 03 '14 at 06:09
  • 2
    @dmiller309: Do you happen to have included `www.` in the `ServerAlias`? – cherouvim May 03 '14 at 13:28
  • 2
    You're right, I accidentally put www. in the ServerAlias using the *. wildcard. Because I messed up the ordering of the VirtualHost entries, the *. wildcard had the opportunity to match when I didn't think it would. – dmiller309 May 10 '14 at 21:28
  • 8
    This is the best answer, because it's clean, keeps the path (unlike answer #1) and doesn't use Rewrite. – schieferstapel Jan 31 '15 at 09:35
34

To remove www from your URL website use this code in your .htaccess file:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1$1 [R=301,L]

To force www in your website URL use this code on .htaccess

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^YourSite.com$
RewriteRule ^(.*)$ http://www.yourSite.com/$1 [R=301]
RewriteCond %{REQUEST_fileNAME} !-d
RewriteCond %{REQUEST_fileNAME} !-f
RewriteRule ^(([^/]+/)*[^./]+)$ /$1.html [R=301,L]

Where YourSite.com must be replaced with your URL.

kloddant
  • 1,026
  • 12
  • 19
25
    <VirtualHost *:80>
       DocumentRoot "what/ever/root/to/source"
       ServerName www.example.com

       <Directory "what/ever/root/to/source">
         Options FollowSymLinks MultiViews Includes ExecCGI
         AllowOverride All
         Order allow,deny
         allow from all
         <What Ever Rules You Need.>
      </Directory>

    </VirtualHost>

    <VirtualHost *:80>
      ServerName example.com
      ServerAlias *.example.com
      Redirect permanent / http://www.example.com/
    </VirtualHost>

This is what happens with the code above. The first virtual host block checks if the request is www.example.com and runs your website in that directory.

Failing which, it comes to the second virtual host section. Here anything other than www.example.com is redirected to www.example.com.

The order here matters. If you add the second virtualhost directive first, it will cause a redirect loop.

This solution will redirect any request to your domain, to www.yourdomain.com.

Cheers!

Dishan Philips
  • 266
  • 3
  • 2
18

Redirection code for both non-www => www and opposite www => non-www. No hardcoding domains and schemes in .htaccess file. So origin domain and http/https version will be preserved.

APACHE 2.4 AND NEWER

NON-WWW => WWW:

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ %{REQUEST_SCHEME}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

WWW => NON-WWW:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ %{REQUEST_SCHEME}://%1%{REQUEST_URI} [R=301,L]

Note: not working on Apache 2.2 where %{REQUEST_SCHEME} is not available. For compatibility with Apache 2.2 use code below or replace %{REQUEST_SCHEME} with fixed http/https.


APACHE 2.2 AND NEWER

NON-WWW => WWW:

RewriteEngine On

RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

... or shorter version ...

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|offs
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

WWW => NON-WWW:

RewriteEngine On

RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]

RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]

... shorter version not possible because %N is available only from last RewriteCond ...

mikep
  • 5,880
  • 2
  • 30
  • 37
16

This is similar to many of the other suggestions with a couple enhancements:

  • No need to hardcode the domain (works with vhosts that accept multiple domains or between environments)
  • Preserves the scheme (http/https) and ignores the effects of previous %{REQUEST_URI} rules.
  • The path portion not affected by previous RewriteRules like %{REQUEST_URI} is.

    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^(.*)$ %{REQUEST_SCHEME}://www.%{HTTP_HOST}/$1 [R=301,L]
    
weotch
  • 5,788
  • 6
  • 35
  • 42
10
RewriteCond %{HTTP_HOST} ^!example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]

This starts with the HTTP_HOST variable, which contains just the domain name portion of the incoming URL (example.com). Assuming the domain name does not contain a www. and matches your domain name exactly, then the RewriteRule comes into play. The pattern ^(.*)$ will match everything in the REQUEST_URI, which is the resource requested in the HTTP request (foo/blah/index.html). It stores this in a back reference, which is then used to rewrite the URL with the new domain name (one that starts with www).

[NC] indicates case-insensitive pattern matching, [R=301] indicates an external redirect using code 301 (resource moved permanently), and [L] stops all further rewriting, and redirects immediately.

Simon Hayter
  • 3,131
  • 27
  • 53
Curtis Tasker
  • 11,115
  • 2
  • 23
  • 23
10

If you are using Apache 2.4 ,without the need to enable the rewrite apache module you can use something like this:

# non-www to www
<If "%{HTTP_HOST} = 'domain.com'">
  Redirect 301 "/" "http://www.domain.com/"
</If>
sys0dm1n
  • 819
  • 6
  • 13
  • 3
    Underrated answer. Using this, additional vhosts can be avoided which is good for automated Let'sEncrypt scripts. – Paul Jun 04 '19 at 11:33
  • Plus, if you are using ANSIBLE, since ANSIBLE 2.0 you can now easily insert a block into a file in one task, more details here https://docs.ansible.com/ansible/2.5/modules/blockinfile_module.html – sys0dm1n Jun 06 '19 at 08:21
5

I ran this...

 RewriteEngine on
 RewriteCond %{HTTP_HOST} !^www.*$ [NC]
 RewriteRule ^/.+www\/(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

I need this to be universal for 25+ domains on our new server, so this directive is in my virtual.conf file in a <Directory> tag. (dir is parent to all docroots)

I had to do a bit of a hack on the rewrite rule though, as the full docroot was being carried through on the pattern match, despite what http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html says about it only being stuff after the host and port.

Andrew Deal
  • 91
  • 1
  • 1
3

Redirect domain.tld to www.

The following lines can be added either in Apache directives or in .htaccess file:

RewriteEngine on    
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
  • Other sudomains are still working.
  • No need to adjust the lines. just copy/paste them at the right place.

Don't forget to apply the apache changes if you modify the vhost.

(based on the default Drupal7 .htaccess but should work in many cases)

xaa
  • 818
  • 13
  • 13
3
<VirtualHost *:80>
    ServerAlias example.com
    RedirectMatch permanent ^/(.*) http://www.example.com/$1
</VirtualHost>

This will redirect not only the domain name but also the inner pages.like...

example.com/abcd.html               ==>    www.example.com/abcd.html
example.com/ab/cd.html?ef=gh   ==>    www.example.com/ab/cd.html?ef=gh

Aneesh R S
  • 3,807
  • 4
  • 23
  • 35
3

This is simple!

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
kalehmann
  • 4,821
  • 6
  • 26
  • 36
Krishan Kumar
  • 394
  • 4
  • 13
2

Try this:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteRule ^(.*) http://www.example.com$1 [R=301]
Simon Hayter
  • 3,131
  • 27
  • 53
Mark Ursino
  • 31,209
  • 11
  • 51
  • 83
2

Do not always use Redirect permanent (or why it may cause issues in future)

If there is a chance that you will add subdomains later, do not use redirect permanent.

Because if a client has used a subdomain that wasn't registred as VirtualHost he may also never reach this subdomain even when it is registred later.

redirect permanent sends an HTTP 301 Moved Permanently to the client (browser) and a lot of them cache this response for ever (until cache is cleared [manually]). So using that subdomain will always autoredirect to www.*** without requesting the server again.

see How long do browsers cache HTTP 301s?

So just use Redirect

<VirtualHost *:80>
  ServerName example.com

  Redirect / http://www.example.com/
</VirtualHost>

Apache.org - When not to use mod_rewrite

Apache.org - Canonical Hostnames

Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
2

To 301 redirect all requests made directly to the domain to www you can use:

RewriteEngine On

RewriteCond %{HTTP_HOST} !^([^.]+\.[^.]+){2,}$ [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

The benefit of this is that this will work if you have any valid subdomains, e.g.

example.com REDIRECTED TO www.example.com

foo.example.com NO REDIRECT

bar.example.com NO REDIRECT

Pencho Ilchev
  • 3,201
  • 18
  • 21
1

RewriteEngine On RewriteCond %{HTTP_HOST} ^yourdomain.com [NC] RewriteRule ^(.*)$ http://www.yourdomain.com/$1 [L,R=301]

check this perfect work

1

-If you host multiple domain names (Optional)

-If all those domain names are using https (as they should)

-if you want all those domain names to use www dot domainName

This will avoid doble redirection (http://non www to http://www and then to https://www)

<VirtualHost *:80>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^(.*)$ https://www.%1$1 [R=301,L]
</VirtualHost>

And

<VirtualHost *:443>
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

You should change the redirection code 301 to the most convenient one

YOGO
  • 531
  • 4
  • 5
1

If you want to load only the https version of www, use the below configurations in apache virtual host file. all these can have in a single file.

redirecting all http to https of www:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    Redirect permanent / https://www.example.com/
</VirtualHost>

redirecting https non-www to https www:

<VirtualHost *:443>
    ServerName example.com
    Redirect permanent / https://www.example.com/
</VirtualHost>

real server configuration

<VirtualHost *:443>
    ServerAdmin hostmaster@example.com
    DocumentRoot "/path/to/your/sites/.htaccess-file-folder"
    SetEnv APPLICATION_ENV "production"

    <Directory "/path/to/your/sites/.htaccess-file-folder">
            Options Indexes FollowSymLinks
            DirectoryIndex index.php index.html
            AllowOverride All
            Order allow,deny
            Allow from all
    </Directory>
    ServerName www.example.com
    
    SSLEngine ON
    SSLCertificateFile "/path/to/your/example.cert.pem"
    SSLCertificateKeyFile "/path/to/your/example.key.pem"

    ErrorLog /path/to/your/example.com-error.log
    CustomLog /path/to/your/example.com-access.log combined
    #Your other configurations if you have
</VirtualHost>
Janaka R Rajapaksha
  • 3,585
  • 1
  • 25
  • 28
0

If using the above solution of two <VirtualHost *:80> blocks with different ServerNames...

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / http://www.example.com/
</VirtualHost>
<VirtualHost *:80>
    ServerName www.example.com
</VirtualHost>

... then you must set NameVirtualHost On as well.

If you don't do this, Apache doesn't allow itself to use the different ServerNames to distinguish the blocks, so you get this error message:

[warn] _default_ VirtualHost overlap on port 80, the first has precedence

...and either no redirection happens, or you have an infinite redirection loop, depending on which block you put first.

Stuart Caie
  • 2,803
  • 14
  • 15
0

The code I use is:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
Simon Hayter
  • 3,131
  • 27
  • 53
0

I've just have a same problem. But solved with this

RewriteEngine On RewriteCond %{HTTP_HOST} !^www\. RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

This rule redirecting non-www to www.

And this rule to redirecting www to non-www

RewriteEngine On RewriteCond %{HTTP_HOST} !^my-domain\.com$ [NC] RewriteRule ^(.*)$ http://my-domain.com/$1 [R=301,L]

Refer from http://dense13.com/blog/2008/02/27/redirecting-non-www-to-www-with-htaccess/

0

I had a similar task on a WP Multisite, where the redirection rule had to be generic (for any given domain I'd add to the network). I solved first adding a wildcard to the domain (parked domain). Note the . after .com.

CNAME * domain.com.

And then I added the following lines to the .htaccess file at the root of my multisite. I guess it'd work for any site.

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

Hopefully this will help.

ps. If you'd like to redirect from not www to www, change the last line into

RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
0

This works for me:

RewriteCond %{HTTP_HOST} ^(?!www.domain.com).*$ [NC]
RewriteRule ^(.*)$  http://www.domain.com$1  [R=301,L]

I use the look-ahead pattern (?!www.domain.com) to exclude the www subdomain when redirecting all domains to the www subdomain in order to avoid an infinite redirect loop in Apache.

Mauricio Sánchez
  • 4,602
  • 1
  • 23
  • 15
0

This is my own site's configuration, and works like a charm.

<IfModule mod_ssl.c>
  <VirtualHost *:443>
    ServerAdmin admin@domain.com

    ServerName www.domain.com
    ServerAlias domain.com

    DocumentRoot /var/www/html/domain

    <Directory /var/www/html/domain/>
      Options FollowSymLinks
      AllowOverride All
      Require all granted
    </Directory>

    # Redirect non-www to www
    RewriteEngine On

    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/domain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
  </VirtualHost>
</IfModule>
Usama Munir
  • 589
  • 9
  • 11
-1

I found it easier (and more usefull) to use ServerAlias when using multiple vhosts.

<VirtualHost x.x.x.x:80>
    ServerName www.example.com
    ServerAlias example.com
    ....
</VirtualHost>

This also works with https vhosts.

Fabian76
  • 389
  • 2
  • 11
  • Another drive-by downvote. Care to explain, oh mighty god of httpd who couldn't be bothered to explain the downvote? – Anthony Aug 25 '15 at 01:35
  • 1
    This makes it so that you have multiple domains hosting the same site. Depending on your situations and what your underlying webserver is running you're going to have issues with cookies not carrying over, people confused, and search engine problems (which will see this as 2 different sites). – Jeffrey Van Alstine Oct 12 '16 at 15:37