Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Apache: Users

mod_rewrite infinite loop problem

 

 

Apache users RSS feed   Index | Next | Previous | View Threaded


dbylsma at musiciansfriend

Apr 25, 2008, 1:32 PM

Post #1 of 4 (231 views)
Permalink
mod_rewrite infinite loop problem

URL for product pages used to look like this:

/product?sku=SKU

In our new version, each product is getting a nice looking path
assigned. New URLs are of the form

/product/PRODUCT_PATH?sku=SKU

I create a txt rewrite map file. Here is an example /etc/httpd/conf/sku_to_path.txt:

000001 Path_To_Product1

In order to redirect from the old to the new form, I have the following
config:

RewriteMap sku_to_path
txt:/etc/httpd/conf/sku_to_path.txt

RewriteCond %{REQUEST_URI} ^/product$
RewriteCond %{QUERY_STRING} sku=([0-9A-Z]+)
RewriteRule .* /product/{sku_to_path:%1} [R=301,L]

This works fine, /product?sku=000001 maps to /product/Path_To_Product1?sku=000001 and when the
server gets the request for /product/Path_To_Product1?sku=000001, it's not
rewritten because it fails the match ^/product$

Here is my problem. I have further requirements that the path for a
product is allowed to change over time (marketers love to change their
minds), and URL with the old path (which lives in the Google index we
hope) should redirect to the new path. For example, if my
sku_to_path.txt changes to

000001 New_Path_To_Product1

I need /product/Path_To_Product1?sku=000001 to
redirect to
/product/New_Path_To_Product1?sku=000001
If I try removing the $ from the ^/product$ match above to accomplish
this, I get infinite redirects, since the request for /product/New_Path_To_Product1?sku=000001 matches
all the conditions and gets rewritten to itself over and over again.

The following attempt to fix this problem fails because
%{ENV:INCOMING_PATH} on the right side of the RewriteCond is not expanded

RewriteMap sku_to_path
txt:/static/73/maps/musiciansfriend.com/sku_to_path.txt

RewriteCond %{REQUEST_URI} ^/product/(.*)
RewriteRule ^ - [E=INCOMING_PATH:%1]

RewriteCond %{QUERY_STRING} sku=([0-9A-Z]+)
RewriteCond ${sku_to_path:%1} !%{ENV:INCOMING_PATH}
RewriteRule .* /product/${sku_to_path:%1} [R=301,L]

I have a solution to this problem, but I'm wondering whether there is a
simpler way. Here is my solution:

I created a rewrite map program - it takes a string with two substrings
separated by ":". If the left is the same as the right, it returns 0,
if different it returns 1

#!/usr/bin/perl
# /etc/httpd/different.pl
$| = 1;
while (<STDIN>) {
chomp;
($first, $second) = split (/:/);
if ( $first eq $second) { print "0\n";}
else { print "1\n"; }
}

My working mod_rewrite config is

RewriteMap sku_to_path txt:/etc/httpd/conf/sku_to_path.txt
RewriteMap different prg:/etc/httpd/different.pl

RewriteCond %{REQUEST_URI} ^/product(.*)
RewriteRule ^ - [E=INCOMING_PATH:%1]

RewriteCond %{QUERY_STRING} sku=([0-9A-Z]+)
RewriteRule ^ - [E=CORRECT_PATH:/${sku_to_path:%1}]

RewriteCond ${different:%{ENV:CORRECT_PATH}:%{ENV:INCOMING_PATH}} 1
RewriteRule .* /product%{ENV:CORRECT_PATH} [R=301,L]

Is there a simpler way?

-David Bylsma



---------------------------------------------------------------------
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[at]httpd.apache.org
" from the digest: users-digest-unsubscribe[at]httpd.apache.org
For additional commands, e-mail: users-help[at]httpd.apache.org


joshua at slive

Apr 26, 2008, 11:49 AM

Post #2 of 4 (211 views)
Permalink
Re: mod_rewrite infinite loop problem [In reply to]

On Fri, Apr 25, 2008 at 4:32 PM, David Bylsma
<dbylsma[at]musiciansfriend.com> wrote:

>
> Is there a simpler way?

I would probably avoid the program rewrite map (which is a potential
bottleneck). There are several ways to do this. One very simple one
would be to make your RewriteRule something like
RewriteRule .* /product/{sku_to_path:%1}?rewritten [QSA,R=301,L]
and then use a RerwiteCond to avoid applying the RewriteRule whenever
"rewritten" is in the query string.

Another solution would be to have two text maps: sku_to_path and
another listing only the sku's that need to be changed. Then you can
have a new RewriteRule that is applied to /product/ URLs only if the
sku is in the list of sku's that need to be changed.

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[at]httpd.apache.org
" from the digest: users-digest-unsubscribe[at]httpd.apache.org
For additional commands, e-mail: users-help[at]httpd.apache.org


dbylsma at musiciansfriend

Apr 28, 2008, 8:47 AM

Post #3 of 4 (203 views)
Permalink
Re: mod_rewrite infinite loop problem [In reply to]

On Sat, Apr 26 at 11:49 AM, Josua Silve
<jslive[at]gmail.com> wrote:

> I would probably avoid the program rewrite map (which is a potential
bottleneck).

Agreed, unfortunately, neither of your suggestions can be implemented in
my environment:

> One very simple one would be to make your RewriteRule something like
RewriteRule .* /product/{sku_to_path:%1}?rewritten [QSA,R=301,L]

This will not work if a URL that's correct today (and makes its way into
the Google index with the "rewritten" query param) is changed tomorow.

> Another solution would be to have two text maps: sku_to_path and
another listing only the sku's that need to be changed.

This would be the best, but unfortunately, our product information
system does not keep "last modified" on the product path, much less a
history of what values used to be. I just don't have data available to
create this map.

===another solution===

I have thought of another solution that avoids the rewrite program. I
could make a rewrite map that contains every valid product URL and maps
it to 1. e.g. /etc/httpd/good_product_urls.txt

/product/New_Path_To_Product1?sku=000001 1

Then add a rule like:

RewriteMap good_product_urls txt:/etc/httpd/good_product_urls.txt

# skip product path rewriting if the URL is already correct
RewriteCond %{REQUEST_URI} ^/product
RewriteCond ${good_product_urls:%{REQUEST_URI}?%{QUERY_STRING}} 1
RewriteRule ^ - [S=1]

...Rule for product path rewrite



---------------------------------------------------------------------
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[at]httpd.apache.org
" from the digest: users-digest-unsubscribe[at]httpd.apache.org
For additional commands, e-mail: users-help[at]httpd.apache.org


dbylsma at musiciansfriend

May 15, 2008, 4:40 PM

Post #4 of 4 (143 views)
Permalink
Re: mod_rewrite infinite loop problem [In reply to]

David Bylsma wrote:
> On Sat, Apr 26 at 11:49 AM, Josua Silve
> <jslive[at]gmail.com> wrote:
>
>
>> I would probably avoid the program rewrite map (which is a potential
>>
> bottleneck).
>
>
In the end, we have opted for use of the rewrite program, rewritten in c
for speed. So far it appears to perform just fine.

---------------------------------------------------------------------
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[at]httpd.apache.org
" from the digest: users-digest-unsubscribe[at]httpd.apache.org
For additional commands, e-mail: users-help[at]httpd.apache.org

Apache users RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.