9

I'm trying to redirect an url without www. to www.version (example.com to www.example.com). I use the usual

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

This works on all my other projects. However on this particular site, it ends with a redirect loop. Here's the weird part: I tried to curl the non-www version to see what headers it sends using curl --get http://example.com --dump-header domain.header > domain.html. The header file looked like this:

HTTP/1.1 301 Moved Permanently
Date: Mon, 06 Jun 2011 14:45:16 GMT
Server: Apache/2.2.16 (Debian)
Location: http://example.com/
Vary: Accept-Encoding
Content-Length: 310
Content-Type: text/html; charset=iso-8859-1

However, the resulting HTML file was this:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://www.example.com/">here</a>.</p>
<hr>
<address>Apache/2.2.16 (Debian) Server at example.com Port 80</address>
</body></html>

(note the address difference between the files) Does anybody know how to fix this (and what the hell is causing it)? Any other url rewriting directives work fine.

EDIT: rewrite log contained this: (the site is accessed by a lot of people so the rewrite log got quite long, I'm not 100% sure if this is the right part)

192.168.1.221 - - [06/Jun/2011:17:49:32 +0200] [example.com/sid#b797f948][rid#b7d2c1c8/initial] (3) [perdir /var/www/oup/81/] strip per-dir prefix: /var/www/oup/81/ ->
192.168.1.221 - - [06/Jun/2011:17:49:32 +0200] [example.com/sid#b797f948][rid#b7d2c1c8/initial] (3) [perdir /var/www/oup/81/] applying pattern '(.*)' to uri ''
192.168.1.221 - - [06/Jun/2011:17:49:32 +0200] [example.com/sid#b797f948][rid#b7d2c1c8/initial] (2) [perdir /var/www/oup/81/] rewrite '' -> 'http://www.example.com/'
192.168.1.221 - - [06/Jun/2011:17:49:32 +0200] [example.com/sid#b797f948][rid#b7d2c1c8/initial] (2) [perdir /var/www/oup/81/] explicitly forcing redirect with http://www.example.com/
192.168.1.221 - - [06/Jun/2011:17:49:32 +0200] [example.com/sid#b797f948][rid#b7d2c1c8/initial] (1) [perdir /var/www/oup/81/] escaping http://www.example.com/ for redirect
192.168.1.221 - - [06/Jun/2011:17:49:32 +0200] [example.com/sid#b797f948][rid#b7d2c1c8/initial] (1) [perdir /var/www/oup/81/] redirect to http://www.example.com/ [REDIRECT/301]

The access log line (probably the right one):

192.168.1.221 - - [06/Jun/2011:17:49:32 +0200] "GET / HTTP/1.1" 301 555 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.77 Safari/534.24"

The definition of the virtualhost:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        ServerName example.com
        ServerAlias example.com www.example.com
        DocumentRoot /var/www/example/
        <Directory />
                Options FollowSymLinks
                AllowOverride All
        </Directory>
        <Directory /var/www/example/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride All
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

EDIT2: okay, I just figured out that if I do this (resigned and attempted to redirect this without .htaccess):

//if clause determining that we're running on example.com and not www.example.com
header('HTTP/1.1 301 Moved Permanently');
header('Location: http://www.example.com' . $_SERVER['REQUEST_URI']);
header('Connection: close');

It causes EXACTLY THE SAME redirect loop. Seriously, what the hell? Does anyone have an idea what might possibly be causing this?

Jenny D
  • 27,780
  • 21
  • 75
  • 114
cypher
  • 91
  • 4
  • Did you compile Apache yourself, or? It should be impossible for the Location header to differ from what's in the page since they're taken from the same variable in this case, so that's pretty odd. I assume that the requests are passed directly to Apache, right, there's no other server sitting inbetween? – Tim Stone Jun 15 '11 at 01:22
  • I didn't compile apache myself and thete's no other server in between. –  Jun 15 '11 at 11:22
  • probably your NS server is not configured properly – venimus Jun 16 '11 at 10:52
  • 4
    It isn't necessary to repeat the server name in the ServerAlias entry. – chris Jul 28 '11 at 01:48
  • can you put all content of file here – undone Aug 20 '11 at 00:52
  • it seems that you've already solved your issue, why don't you mark an answer as correct ? – Pedro Lobito Aug 22 '11 at 07:14
  • I haven't solved my issue, none of these answers fixes my problem. –  Aug 22 '11 at 07:47
  • Could you make your RewriteLogLevel to 9, and provide more rewrite log info at least to show a loop happens. – xdazz Aug 25 '11 at 16:49
  • Just a wild guess, but what happens when you change the ServerName in the virtualHost to www.domain.cz? –  Aug 26 '11 at 09:24
  • @Louis not yet, but I intend to. –  Aug 26 '11 at 11:52
  • @Boo no difference. –  Aug 26 '11 at 11:52
  • I copied this config and can't reproduce the issue you are seeing(Apache/2.2.19 on OS X). One thing that is still interesting is that you have allowoverride set. Are you absolutely sure there aren't other .htaccess files in the /var/www/oup/81 path that are affecting this? If you turn off all the allowoverrides and put the rewrite rules in the httpd.conf what happens? – polynomial Aug 30 '11 at 00:38
  • Given @polynomial's comment here, I suggest you try this on a completely fresh Apache server (on a PC or whatever) so you can determine if it's your rewrite config or something else in the environment that's causing this. The fact that similar config works on other servers, but not this one, makes me think there's something else in the environment. Turning off AllowOverride is a good idea too. – RichVel Sep 01 '11 at 06:54
  • What happens when you go directly to the www-prefixed page? Does that work as expected or is there some kind of rewrite there too? – Jenny D Feb 03 '15 at 18:46
  • Also, if all you're doing with `example.com` is to redirect it to `www.example.com`, why are they in the same virtualhost in the first place? Why not simply have a virtualhost for `example.com` which only contains the redirect - then there will be no possibility of loops. – Jenny D Feb 03 '15 at 18:47

11 Answers11

2

What strikes me as odd is the Location: http://domain.cz/ header line reported by CURL. You never redirect to that domain. The redirect log also doesn't contain any mention of it.

Somehow the Location header seems to be altered after modrewrite does its stuff, and since you tried changing the header with PHP as well, the Location header is apparently changed after the request is processed. The only explanation I can think of is that you are modifying the location header with mod_header somewhere.

Did you check all configuration files (httpd.conf, the included .conf files, and the .htaccess file) if you somewhere find a line similar to this:

Header set Location (...)

or

Header edit Location (...)
Jakob Egger
  • 121
  • 3
  • I haven't found anything like this. –  Aug 26 '11 at 11:51
  • 2
    Are you directly connecting to Apache, or is there some caching or proxy server inbetween that might change headers? The ProxyPassReverse directive might also change the location header (http://httpd.apache.org/docs/2.0/mod/mod_proxy.html#ProxyPassReverse). –  Aug 28 '11 at 08:01
  • there might be some proxy inbetween, I'll have a look into it as soon as I get to work tomorrow. –  Aug 28 '11 at 18:32
  • @Jakob Egger - I haven't found ProxyPassReverse directive anywhere. – cypher Aug 29 '11 at 13:46
1

Can you try this alternative mod_rewrite code:

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
anubhava
  • 411
  • 4
  • 8
  • This failed exactly the same way. –  Jun 06 '11 at 15:28
  • can you enable RewriteLog and see what it spits out. – anubhava Jun 06 '11 at 15:31
  • And how exactly can I do that? :-) –  Jun 06 '11 at 15:35
  • Please see here: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#rewritelog Only thing is that this directive goes into apache config NOT in .htaccess. – anubhava Jun 06 '11 at 15:38
  • I've added the rewrite log contents to the question. –  Jun 06 '11 at 15:56
  • RewriteLog seems to be alright and doing exactly it's supposed to be doing i.e. redirecting `http://domain.cz` to `http://www.domain.cz` and there is NO lines in there to indicate infinite looping. Can you clear all the browser cache and restart your browser to test again. – anubhava Jun 06 '11 at 16:08
  • This I already tried. From several different browsers, using cURL from several different servers. It seems that somehow mod_rewrite doesn't actually modify the headers (even if it says so) - that would explain the difference between the dumped header file and the resulting html file. But it still doesn't explain why. –  Jun 06 '11 at 16:13
  • 1
    I copied same rule (as my answer above) to my Apache installation and ran the same curl command you have in your question and got `Location: http://www.domain.com/` as part of my headers so in my case headers and html both are showing same domain i.e. `www.domain.com`. Can you also paste you relevant access.log lines in your question above? – anubhava Jun 06 '11 at 16:20
  • There, I pasted it, hopefully it's the right one. –  Jun 06 '11 at 16:43
  • I compared that with my access.lg and it looks alright too. That `301` line will be immediately followed by a `200` line I suppose in your access.log. – anubhava Jun 06 '11 at 17:00
  • No, it is followed by a lot of 301s. –  Jun 06 '11 at 20:51
  • Hmm that's the problem, looks like there is another redirect going on somewhere and causing this looping on your host. Do you have WP or any other CMS running by any chance? – anubhava Jun 06 '11 at 20:53
  • No, the application is stand-alone on its own server. –  Jun 06 '11 at 21:06
  • Wish I could do more but all the symptoms are showing normalcy on your end and not really giving me any scope of fixing things. – anubhava Jun 06 '11 at 23:53
1

In addition to enabling rewritelog (if you have access to change the httpd.conf) you should remove the application that lives on this site from the equation. Remove/rename temporarily the default index.php (or whatever index page is serving your app) to be sure it's not causing this.

There are many reports of applications (e.g. wordpress) causing these apache default redirect page to appear if they are misconfigured.

Also, check the rest of the apache config to see if there are any other 'redirect' instructions that might be conflicting.

Gavin C
  • 145
  • 6
  • The application is alright, I tried it on a different server and different domain (copied the whole app) and it worked alright. I guess it's something in apache configuration, but I can't figure out what. –  Jun 06 '11 at 16:15
  • The app may be ok, but may be also conflicting with the setup on *this* server. It sounds like your app is currently in production so I can see how 'disabling it' isn't ideal. For fun, you might add a query string to the end of the redirection as a flag to aid discovery - so /$1?nowww=1 or something similar. – Gavin C Jun 06 '11 at 16:23
  • No, it is NOT in production. –  Jun 06 '11 at 16:30
  • Oh cool, then can't hurt to move the index file out of the way to 100% exclude it as part of the problem :) – Gavin C Jun 06 '11 at 16:33
  • Oh, damned, what I meant to write was that tis IS in production, dunno how this happenned :-) –  Jun 06 '11 at 16:40
  • As you've surmised, apache (maybe as a result of app issue, not gonna rule that out yet) are intercepting the 301 redirects and showing the default apache error message. Might want to paste up in pastebin a redacted version of the httpd.conf - and the rest of the .htaccess to see if there is another conflict there too. – Gavin C Jun 06 '11 at 16:56
0

could you try to use [NC] instead of [nc], might be so simple

venimus
  • 109
  • 1
0

I hope you have server access, Added the redirect line after site document folder specified followed

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

If you dont have access for server, add those line on httaccess starting / change the portion.

May be you havent add "RewriteEngine on" before the redirection.

  • I have added `RewriteEngine on`, as I said, it works on another server properly, just not on this one. –  Jun 15 '11 at 11:23
  • AllowOverride All allow from all add those lines in your server config file –  Jun 15 '11 at 12:51
0

Try:

RewriteCond %{HTTP_HOST} ^domain.cz [NC]
RewriteRule (.*) http://www.domain.cz/$1 [R=301,L]
Shef
  • 284
  • 1
  • 3
  • 10
0

Be sure to have Options +FollowSymLinks if you are working within a directory context.

Otherwise if you are using name based virtual hosts, try:

<VirtualHost *:80>
  ServerName domain.cz
  Redirect / http://www.domain.cz/
</VirtualHost>

<VirtualHost *:80>
  ServerName www.domain.cz
  # whatever else
</VirtualHost>
chris
  • 136
  • 5
  • I've updated the question with definition of the VirtualHost. –  Jun 16 '11 at 12:39
  • Did you give the above multiple VirtualHost solution a try, or are you set on using mod_rewrite? – chris Jul 28 '11 at 01:49
  • At firts, I didn't want to use multiple VirtualHosts, but given the circumstances I tried it anyway and it didn't help. –  Aug 22 '11 at 07:48
0

After reading all the answers you could check de /etc/hosts file... maybe all your checks are from your computer. Try to access from a different location.

0

I have a second idea. The server log you posted shows an adress of "192.168.1.221", which is an adress from the local network. Do all log entries show the same IP adress? If this is the case, there is a proxy between you and the server. This proxy probably uses ProxyPassReverse or Header edit to change the Location header.

This is a usual setup to circumvent the problem when the backend server puts its own hostname into the Location header, rather than the hostname of the external proxy server.

If there really is a proxy server, you will have to change the configuration of the proxy server rather than the configuration of the backend server, as the proxy will always overwrite the information.

This means that all the time we have been looking at the wrong server: The problem is with the proxy server!

Jakob Egger
  • 121
  • 3
  • Tomorrow I'm calling tech support of the company that runs this server. I think that must be it, I'll let you know. – cypher Aug 30 '11 at 23:01
0

Could be unprintable chars like null in the .htaccess file.

hexdump -C .htaccess
Lucas Kauffman
  • 16,880
  • 9
  • 58
  • 93
Charlie
  • 181
  • 2
0

I believe you are missing a $ sign after your rewrite condition. Please try:

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