Forum Moderators: phranque

Message Too Old, No Replies

301 Redirect Loop

301 Redirect Loop htaccess prestashop

         

Version1beta

1:09 pm on Feb 18, 2012 (gmt 0)

10+ Year Member



Apologies if this has been covered before, but I’ve searched high and low for a solution to my problem but haven’t come across anything yet. My problem is that I’m getting 301 loops…nothing new there I know. I’m using Prestashop which by default puts a category ID before the name of the category in links – for example: http://www.example.com/shop/5-laptops. I have changed the PHP code so that this no longer happens and the links are now of the form http://www.example.com/shop/laptops. However, for search engine reasons, I still want the old links (containing the category ID) to be active. The original link (e.g. http://www.example.com/shop/5-laptops) is itself a rewrite to something like http://www.example.com/shop/category.php?id_category=5 which I believe is achieved by the following two lines in the .htaccess file (generated automatically by Prestashop):

RewriteRule ^([0-9]+)\-[a-zA-Z0-9-]*(/[a-zA-Z0-9-]*)+ /shop/category.php?id_category=$1&noredirect=1 [QSA,L]
RewriteRule ^([0-9]+)\-[a-zA-Z0-9-]* /shop/category.php?id_category=$1 [QSA,L]


So, I need http://www.example.com/shop/5-laptops and http://www.example.com/shop/laptops to link to http://www.example.com/shop/category.php?id_category=5 and I also need http://www.example.com/shop/category.php?id_category=5 to link to http://www.example.com/shop/laptops and therein lies my problem. I cannot find a way of achieving this without getting stuck in a loop.

I can get a redirect to take place by adding the following line (before the 2 lines above):

RewriteRule ^laptops$ /shop/category.php?id_category=5 [QSA,L]

but as soon as I add R=301, I get stuck in a loop.

I think my brain is also stuck in a loop now so any help would be greatly appreciated.

g1smd

9:00 pm on Feb 18, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



When you want to redirect requests that might result in a loop add a RewriteCond before the rule. This will test THE_REQUEST so that only direct client requests are redirected and not those where the rule pattern matches because of a prior internal rewrite.

Version1beta

10:11 pm on Feb 18, 2012 (gmt 0)

10+ Year Member



Thanks for the response g1smd.

I’ve tried the following lines:

RewriteCond %{THE_REQUEST} ^laptops\ HTTP/
RewriteRule ^laptops$ /shop/category.php?id_category=5 [R=301,L]


This gives a 404 error. I've also tried adding a NOT (!) operator in front of ^laptops on the first line, but this gives a loop again.

I'm working my way through the Apache Rewrite Charter but I still can't get it. What am I doing wrong? Thanks again.

g1smd

10:32 pm on Feb 18, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



THE_REQUEST is the literal GET or POST request sent by your browser, such as:

GET /somepath/somefile?someparam HTTP/1.1


You can see this data if you use the Live HTTP Headers for Firefox extension.

You'll need to match that format. See previous threads for various pattern matching suggestions.


Not sure why you added the R flag. That forces a redirect. Your original code was for a rewrite.

Version1beta

9:42 am on Feb 19, 2012 (gmt 0)

10+ Year Member



OK, I *think* I've got it now. The code I've used is as follows:


RewriteEngine on

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /shop/category\.php\?id_category=5\ HTTP/

RewriteRule ^category\.php?id_category=5$ http://www.example.com/shop/laptops? [R=301,L]

RewriteRule ^laptops$ /shop/category.php?id_category=5 [L]

RewriteRule ^([0-9]+)\-[a-zA-Z0-9-]* /shop/category.php?id_category=$1 [QSA,L]


This seems to correctly redirect http://www.example.com/shop/5-laptops and http://www.example.com/shop/category.php?id_category=5 to http://www.example.com/shop/laptops, exactly as I need.

I added the R=301 flag as I want this to be a permanent redirect.

The last line is intended to redirect any URI of the form categoryid-categoryname. For example, it will redirect 5-laptops to /shop/category.php?id_category=5 and 6-peripherals to /shop/category.php?id_category=6. I know I'll also need to add separate rewritecond / rewriterule statements for my other categories (peripherals etc.).

Does this look OK? If you can see any problems or any areas where it can be improved, I'd appreciate your advice. Thanks again.

lucy24

10:11 am on Feb 19, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



RewriteRule ^category\.php?id_category=5$ http://www.example.com/shop/laptops? [R=301,L]


The RewriteRule can't "see" the query string. It can only see the body of the URL: the part that's left if you strip away the domain name from the front and the query from the back.

Minimalist version:

RewriteCond %{THE_REQUEST} \?
RewriteCond %{QUERY_STRING} id_category=5
RewriteRule ^category\.php http://www.example.com/shop/laptops? [R=301,L]

That is:

Condition #1 The Request, as it originally arrived, included a query. Note that THE_REQUEST, by that name, is simply a string-- exactly the way you see it in your logs. So the query here becomes a literal question mark.

Condition #2 The Query contains the element "id_category=5"

How many Categories do you have? If there are 10 or more, you will have to be careful with anchors to make sure 1 and 10 don't get mixed up. Or 5 and 592 or whatever you've got. But if there were that many you'd be looking at rewriting to a script that fixed them up; you wouldn't put 500 separate redirects in htaccess :)

Version1beta

10:47 am on Feb 19, 2012 (gmt 0)

10+ Year Member



Thanks for the response lucy. If I add the following line to the end of your code, everything works fine:

RewriteRule ^laptops$ /shop/category.php?id_category=5? [L]

But as soon as I add R=301 to this line, I get stuck in the loop again. I realized not long after posting my last message that I hadn't included the 301 redirect in two of the lines so what I thought was a solution, erm, wasn't.

Without the 301, I'm concerned that certain search engines will give me duplicate content penalties.

My poor little brain can't work this out I'm afraid.

Fortunately, at present, I only have three categories (5 [laptops], 6 [peripherals] and 7 [desktops]) that I need to redirect so no, I don't intend to add 500 or more :)

lucy24

11:40 am on Feb 19, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



RewriteRule ^laptops$ /shop/category.php?id_category=5? [L]

But as soon as I add R=301 to this line, I get stuck in the loop again.

That's because you don't want to redirect here. The user's address bar now says what you want it to say:

www.example.com/laptops

No more redirecting! All you need to do now is rewrite to the long ugly complicated address where the content really lives.

There are always two parts.

#1 Redirect from ugly URL to pretty URL using [R=301,L]. Don't forget the L! You would think that R implies L, but it doesn't. Always include a Condition looking at THE_REQUEST to make sure you are only redirecting outside requests, not interior rewrites.

In your case you have two different redirects because of that added "5-" business. But the two possible requests are mutually exclusive, so there is no danger of getting into a tangle or running into infinite redirects. Once you've got rid of the 5- it can never raise its head again.

Part 1 is only necessary to pick up people arriving via outdated links or bookmarks. Your internal links will send people directly to:

#2 Rewrite from pretty URL to unattractive location using [L] only. This might be the identical address that you only just finished redirecting away from. But neither humans nor search engines know this.

Version1beta

1:40 pm on Feb 19, 2012 (gmt 0)

10+ Year Member



You're a star lucy. It's all clicked into place now. Among my many, many mistakes, I clearly did not understand the difference between redirects and rewrites but I've got there now. Thanks so much for all your help.

g1smd

5:36 pm on Feb 19, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The confusion is easy to understand.

RewriteRule can be configured to deliver an external redirect or to perform an internal rewrite.

The outcome of both is quite different, but the syntax differences for those is very small.

Once you dig even deeper you'll also see it can be used as a reverse proxy and other things.

This is the point where you might decide to not bother looking at Redirect and RedirectMatch (from mod_alias) ever again and instead use only mod_rewrite functionality - the Swiss Army Knife of server configuration tools.

Version1beta

8:07 pm on Feb 19, 2012 (gmt 0)

10+ Year Member



I'll be perfectly honest in admitting that there is so much more to mod_rewrite than I had ever realized. It is a hugely powerful thing too. I'll continue reading the forums messages and the mod_rewrite documentation and try to fully get my head around it all. Thanks for your help g1smd.

lucy24

8:26 pm on Feb 19, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



the Swiss Army Knife of server configuration tools

... offering a whole range of different ways to hurt yourself in one handy package ;)

You knew I was going to say that, didn't you. Technically it's called a "straight line" (same intonation as "punch line").