You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@httpd.apache.org by Sander Marechal <s....@jejik.com> on 2007/05/17 11:44:28 UTC

[users@httpd] 301 redirect looping with mod_rewrite

Hello,

I am trying to use mod_rewrite (apache 2) to give my website pretty
URLs, but for some reason I get stuck in a 301 redirect loop. I have
looked at the code over and over again. I know what lines cause the loop
but I can't find out why it's looping. There's probably something wrong
with my understanding of mod_rewrite. Anyway, here are the rules I use
(numbered for ease):

This bit takes an old, ugly URL and redirects to a new, pretty URL with
a 301. In my understanding the l stops mod_rewrite and the browser
simply sends out a new request for the new URL. Example:
index.php?t=somepage becomes /page/somepage/

(1) RewriteCond %{query_string} t=([a-z]+)
(2) RewriteRule ^index.php$ /page/%1/? [r=301,l]

The next rule makes sure that the pretty URLs all end in a slash. It
also does a 301 redirect causing the browser to send a new request.

(3) RewriteRule ^page/([^/]+)$ /page/$1/ [r=301,l]

Here I parse the new pretty URL to get the old URL back for processing.

(4) RewriteRule ^page/([^/]+)/$ /index.php?t=$1

Rule 1 and 2 work. I get the pretty URL in my address bar. Rule 3 and 4
also work, but only if I comment out rule 1 and 2. If all 4 rules are
active I get 301 redirects on the new pretty URL. It doesn't matter if
the pretty URL came from rule 1 and 2 or if I manually type a pretty URL
in the address bar.

The thing I don't get: Why would rule 1 and 2 affect a pretty URL? It
doesn't match! Only rule 4 should match a pretty URL, and when rule 4
turns the pretty URL back into an old URL, the rewriting is done.

Unless I completely misunderstand mod_rewrite and for some reason the
rules are parsed *again* after rule 4 has been applied...

Any help would be greatly appreciated. Kind regards,

-- 
Sander Marechal

---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] 301 redirect looping with mod_rewrite

Posted by Sander Marechal <s....@jejik.com>.
Joshua Slive wrote:
> On 5/17/07, Sander Marechal <s....@jejik.com> wrote:
> 
>>
>> > Your problem is that the results of (4) are getting reinjected to
>> > mod_rewrite for processing, and will then obviously match (1) and (2).
>>
>> I figured as much, but can you tell me why it's reinjected? That's the
>> part I really don't understand.
> 
> I'd have to check the code to get the details, but it probably has to
> do with the fact that .htaccess processing happens relatively late in
> the config cycle. Then if you ask mod_rewrite to go to a web-space
> URL-path (as opposed to a file-system path), it needs to restart
> processing in order to let apache do the correct mapping of the URL to
> the file-system location.

I guess it's not that, because your first suggestion (use filesystem
path) didn't work, nor did the second one (add [ns]). Renaming index.php
did work ofcourse, but it's not very elegant.

Could it have something to do with .htaccess being per-directory? So
that if you change from directory with mod_rewrite (from
/page/something/ to / )it processes the .htaccess for the new directory
(wich in this case is the same file)?

-- 
Sander Marechal

---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] 301 redirect looping with mod_rewrite

Posted by Joshua Slive <jo...@slive.ca>.
On 5/17/07, Sander Marechal <s....@jejik.com> wrote:

>
> > Your problem is that the results of (4) are getting reinjected to
> > mod_rewrite for processing, and will then obviously match (1) and (2).
>
> I figured as much, but can you tell me why it's reinjected? That's the
> part I really don't understand.

I'd have to check the code to get the details, but it probably has to
do with the fact that .htaccess processing happens relatively late in
the config cycle. Then if you ask mod_rewrite to go to a web-space
URL-path (as opposed to a file-system path), it needs to restart
processing in order to let apache do the correct mapping of the URL to
the file-system location.

Joshua.

---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] 301 redirect looping with mod_rewrite

Posted by Sander Marechal <s....@jejik.com>.
Joshua Slive wrote:
> On 5/17/07, Sander Marechal <s....@jejik.com> wrote:
> 
>> (1) RewriteCond %{query_string} t=([a-z]+)
>> (2) RewriteRule ^index.php$ /page/%1/? [r=301,l]
>>
>> The next rule makes sure that the pretty URLs all end in a slash. It
>> also does a 301 redirect causing the browser to send a new request.
>>
>> (3) RewriteRule ^page/([^/]+)$ /page/$1/ [r=301,l]
>>
>> Here I parse the new pretty URL to get the old URL back for processing.
>>
>> (4) RewriteRule ^page/([^/]+)/$ /index.php?t=$1
> 
> Are you forced to use .htaccess for this? If not, you should put this
> stuff in the main server context of httpd.conf. It makes things much
> easier, and also gives you access to the RewriteLog, which is the only
> reasonable way to debug mod_rewrite problems.

Unfortunately, yes. This website sits on a regular shared webhost so I
don't have access to mod_rewrite. I do have a test server where I have
full access though.

> Your problem is that the results of (4) are getting reinjected to
> mod_rewrite for processing, and will then obviously match (1) and (2).

I figured as much, but can you tell me why it's reinjected? That's the
part I really don't understand.

> Since I don't use mod_rewrite in .htaccess, I can't tell you exactly
> how to fix this, but here are a few ideas:

Thanks for those. I'll try them out and let you know :-)

-- 
Sander Marechal

---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] 301 redirect looping with mod_rewrite

Posted by Joshua Slive <jo...@slive.ca>.
On 5/17/07, Sander Marechal <s....@jejik.com> wrote:

> (1) RewriteCond %{query_string} t=([a-z]+)
> (2) RewriteRule ^index.php$ /page/%1/? [r=301,l]
>
> The next rule makes sure that the pretty URLs all end in a slash. It
> also does a 301 redirect causing the browser to send a new request.
>
> (3) RewriteRule ^page/([^/]+)$ /page/$1/ [r=301,l]
>
> Here I parse the new pretty URL to get the old URL back for processing.
>
> (4) RewriteRule ^page/([^/]+)/$ /index.php?t=$1

Are you forced to use .htaccess for this? If not, you should put this
stuff in the main server context of httpd.conf. It makes things much
easier, and also gives you access to the RewriteLog, which is the only
reasonable way to debug mod_rewrite problems.

Your problem is that the results of (4) are getting reinjected to
mod_rewrite for processing, and will then obviously match (1) and (2).
Since I don't use mod_rewrite in .htaccess, I can't tell you exactly
how to fix this, but here are a few ideas:

1. Instead of rewriteing to /index.php, rewrite to the complete
filesystem path (eg. /usr/local/apache2/htdocs/index.php).

2. On rule (2) include the [NS] flag.

3. If all else fails, simply rename index.php to index-new.php. Nobody
from the outside world should care about this, since this name is
never used externally. But it will avoid the loop.

Joshua.

---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org