Forum Moderators: phranque

Message Too Old, No Replies

It's me again about a loop

         

Namjies

6:48 pm on May 25, 2010 (gmt 0)

10+ Year Member



Hello
I was trying to help someone redirect all his urls from /***.php to /***

Since it wasn't working, I decided to test it on my server.

This rule is working alone
RewriteRule ^([^.]+).php /$1 [R=301]

but it doesn't if we add this:
RewriteRule ^([^.]+)$ $1.php [L]
RewriteRule ^([^.]+).php /$1 [R=301]

Which indicates me the rule tries to redirect the previous $1.php that is beeing used by /$1 to /$1

But isn't the [L] supposed to stop the url /$1 (using $1.php) from using the second rule? There's no redirect in the first rule, it shouldn't start a new request and go up to the redirect rule.

I'm sure I've done something similar before, but couldn't find how. Else I'll have to use THE_REQUEST to check if the url asked contains .php

But I'm sure I've already done this without THE_REQUEST and I'd like to avoid adding a condition if possible. Am I missing something or do I really need to go with THE_REQUEST?

(hurra, my troubleshooting power is increasing! :/)

jdMorgan

9:02 pm on May 25, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The [L] flag stops processing for the current pass through the mod_rewrite code only. In the .htaccess context, mod_rewrite is recursive, though; It restarts as soon as an [L] flag or the end of the file is reached, whichever comes first.

Only after a complete pass through all mod_rewrite code is made without any rule being invoked is mod_rewrite processing terminated. So, use of the [L] flag is an optimization, a "stop here for now" kind of thing.

Also, if a redirect is done, it's important to realize that the current HTTP transaction is ended, the client will start a new one, and the server will have no memory of the previous transaction.

The following is a correct solution for your problem. Note that all external redirects should be done first, followed by all internal rewrites.

# Externally redirect only direct client requests for .php URLs to extensionless URLs
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.]+\.php([?#][^\ ]*)?\ HTTP/
RewriteRule ^(([^/]+/)*[^.]+)\.php http://www.example.com/$1 [R=301,L]
#
# Internally rewrite requests fore extensionless URLs to .php filepaths
RewriteRule ^(([^/]+/)*[^./]+)$ /$1.php [L]

Note the leading slash added before "$1" in the second rule. This is important to prevent giving the client complete control of the filepath to be accessed on your server.

Note also that you can use %{REDIRECT_STATUS} instead of %{THE_REQUEST} if you prefer. %{REDIRECT_STATUS} will be blank if not previous rewrites have been invoked. However, rules added in server config files or higher-level .htaccess files can break this latter method...

Jim