Forum Moderators: phranque

Message Too Old, No Replies

htaccess redirect loop

         

Sandro87

11:01 pm on May 16, 2009 (gmt 0)

10+ Year Member



Hello,
I have this code:


#redirect whatever.php to /whatever
RewriteRule ^([a-z_-]+)\.(php¦html¦htm¦asp)$ $1 [R=301,L]

#rewrite /whatever to whatever.php
RewriteRule ^([a-z_-]+)$ $1.php

I need to redirect people to /page1 so they can't never see the extensions but only the links without trailing slashes.
The problem with thoserules is that when the second one tries to read from page.php (that exists) it gets the first rule applied too, causing an endless loop.

What condition can I use to prevent the "internal" rewriting to consider the first rule (which applies to navigation only)?

Thank you

Plus, when can I find a full guide with the expiations of all expressions (like [L] [NC] / ^ * )?

[edited by: Sandro87 at 11:03 pm (utc) on May 16, 2009]

jdMorgan

1:37 am on May 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




# Externally redirect only direct client requests for <whatever>.php to /<whatever>
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[a-z_\-]+\.(php¦html?¦asp)(#[^?\ ]*)?(\?[^\ ]*)?\ HTTP/
RewriteRule ^([a-z_\-]+)\.(php¦html?¦asp)$ $1 [R=301,L]
#
# Internally rewrite /<whatever> to <whatever>.php
RewriteRule ^([a-z_\-]+)$ $1.php [L]

Replace all broken pipe "¦" characters with solid pipes before use; Posting on this forum modifies the pipe characters.

> Plus, when can I find a full guide with the expiations of all expressions (like [L] [NC] / ^ * )?

See the resources cited in our Forum Charter (link at top of this page).

Jim

[edited by: jdMorgan at 1:38 am (utc) on May 17, 2009]

Sandro87

1:52 am on May 17, 2009 (gmt 0)

10+ Year Member



Thanks Jim, i'm not home to test right now but i'll let you know.
can you explain me in the meanwhile what the conditions does literally?

jdMorgan

2:01 am on May 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The condition looks at the HTTP request exactly as received from the client, and in the exact form you can see in your raw server access log. The pattern looks for the HTTP Method (such as GET or POST), the URL-path, plus optional fragment, plus optional query string, followed by the HTTP version (1.0 or 1.1)

The redirect will be invoked only if the client requested the URL-path with a filetype extension, and not as a result of the extension being added by your second rule.

Jim

jdMorgan

2:05 am on May 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Since we really don't care about the fragment or the query string in this case, you could also code the RewriteCond as

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[a-z_\-]+\.(php¦html?¦asp)([#?][^\ ]*)?\ HTTP/

Jim

Sandro87

11:46 am on May 17, 2009 (gmt 0)

10+ Year Member



Hello,
I tried it doesn't work. When I type page.php the page appears but there's no redirect in fact the link remains .php . If I type page.html I get 404 error so no redirect here either.

[edited by: Sandro87 at 11:50 am (utc) on May 17, 2009]

jdMorgan

1:24 pm on May 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Did you replace the broken pipe characters, as noted above?

Jim

Sandro87

1:59 pm on May 17, 2009 (gmt 0)

10+ Year Member



Yes

Sandro87

2:31 pm on May 17, 2009 (gmt 0)

10+ Year Member



I don't understand this one.

^[A-Z]+\ /[a-z_\-]+\

Doesn't it mean a link like PAGE/page.php?

jdMorgan

2:50 pm on May 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



THE_REQUEST is the HTTP request line, exactly as received from the client (e.g. browser or search engine robot). It is in the exact format you see in your raw server access logs, e.g.
GET test.php?var=val HTTP/1.1

There may be a typo in the code I posted, but the idea is based on code that has been deployed to hundreds or thousands of servers and it works fine, so any problem here is likely to be subtle. If you have made *any* changes to the code I posted other than fixing the broken pipes, then please re-post the code here for review.

Jim

Sandro87

3:15 pm on May 17, 2009 (gmt 0)

10+ Year Member



That's what I'm using

#redirect whatever.php to /whatever
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[a-z_\-]+\.(php¦html?¦asp)([#?][^\ ]*)?\ HTTP/
RewriteRule ^([a-z_-]+)\.(php¦html¦htm¦asp)$ $1 [R=301,L]

Output

127.0.0.1 - - [17/May/2009:17:16:34 +0200] "GET /dttitalia20/news.php HTTP/1.1" 200 2277

"dttitalia20" is the root dir of the site

[edited by: Sandro87 at 3:18 pm (utc) on May 17, 2009]

jdMorgan

3:31 pm on May 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Note that we should be using a canonical URL in the RewriteRule, and that you did not take advantage of the pattern optimization I posted above. Try:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[a-z_\-]+\.(php¦html?¦asp)([#?][^\ ]*)?\ HTTP/
RewriteRule ^([a-z_-]+)\.(php¦ht[b]ml?¦[/b]asp)$ [i]http://www.example.com/[/i]$1 [R=301,L]

This may clear up any problems with the rewrite base value.

Also, while it was helpful to show the "output" above, it doesn't mean much if you don't also show the "input." -- The less we have to guess at here, the better.

Jim

Sandro87

6:01 pm on May 17, 2009 (gmt 0)

10+ Year Member



Nothing, it won't redirect, it ignores the rules for link with those extensions.

As regards the input, that's what access.log shows: "- -"

jdMorgan

8:28 pm on May 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'll try to be very specific, in case there is something you haven't written that I am making assumptions about here.

As with your original rule, this new one accepts only example.com/<filename>.<filetype> as input.

It will not accept example.com/<directory>/<filename>.<filetype>

So if you are testing by typing in "example.com/dttitalia20/news.php", then it won't redirect.

If you need to accept and redirect subdirectory paths, then you'll need to modify the rules:


# Externally redirect only direct client requests for /<whatever>.php to /<whatever>
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[b]([^/]+/)*[/b][a-z_\-]+\.(php¦html?¦asp)([#?][^\ ]*)?\ HTTP/
RewriteRule ^([b]([^/]+/)*[/b][a-z_\-]+)\.(php¦html?¦asp)$ http://www.example.com/$1 [R=301,L]
#
# Internally rewrite /<whatever> to /<whatever>.php
RewriteRule ^([b]([^/]+/)*[/b][a-z_\-]+)$ $1.php [L]

This code is intended for use in example.com/.htaccess only; It likely won't work elsewhere without modification.

Furthermore, the filename must consist of lowercase characters, hyphens or underscores only, and obviously, only the specified filetypes will be redirected.

Please test this code with no changes whatsoever, except for fixing the broken pipe characters and putting your correct domain name in the first rule. Or, if you must make any other changes, then please post the entire code snippet back again to show your changes.

Completely flush your browser cache before testing any new server-side code.

Please let us know what URLs you typed in, and what results you got in your browser, access log, error log, etc. as applicable.

Jim

Sandro87

12:35 pm on May 18, 2009 (gmt 0)

10+ Year Member



Now it works! Thank you, what does (([^/]+/)* do?

[edited by: Sandro87 at 12:37 pm (utc) on May 18, 2009]

g1smd

12:49 pm on May 21, 2009 (gmt 0)

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



Not-a-slash (one or more times) followed by a slash (the whole lot zero or more times) -- i.e. it detects and captures any level of folder depth.