Forum Moderators: phranque

Message Too Old, No Replies

Unexpected behaviour with [L] in rewriting rule

How to stop the rewrite when a match is found?

         

chrisjoha

8:54 am on Jul 28, 2005 (gmt 0)

10+ Year Member



I'm trying to use two rewriting rules in my .htaccess. If an URL fits the first pattern I want it to rewrite and stop processing. I've tried to stop it with the [L] flag.

I have the following:

RewriteEngine on
RewriteRule ^\_ script_index.php [L]
RewriteRule!(\.(jpg¦gif¦css¦png¦ico)$¦/404.html$) app_index.php [L]

If I comment out the second rule a url such as [mysite...] redirects to script_index.php But if both the rules are active the first rule is bypassed and app_index.php parses the request. Any ideas why?

jdMorgan

2:43 am on Jul 29, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



1) The second rule passes all requests except for those files and filetypes listed, to app_index.php. So be sure that you really want to use the "!" NOT operator there.

2) mod_rewrite in .htaccess is effectively recursive. Once a rewrite is performed, control is passed back up through httpd.conf. There, the newly rewritten URL-path is checked for authorization requirements and for any aliases, rewrites, or redirects that might apply to it. After, that, control is passed back down through all .htaccess files in the new URL-path, checking for applicable access controls and rewrites/redirects. So, the [L] flag only applies to the current pass through your code; It is used to prevent wasting CPU time parsing the rules that follow if you know there is no reason to do so.

Two work-arounds:
1) Add a RewriteCond to each rule, each excluding specific {REQUEST_URI}s from being rewritten by that rule.
2) Use RewriteCond %{THE_REQUEST} to test the client-requested URL, and act only upon the original HTTP request, independent of any rewrites that have ocurred. Note that a redirect ends the current and starts a new HTTP transaction, while a rewrite does not.

Jim

chrisjoha

5:34 pm on Jul 29, 2005 (gmt 0)

10+ Year Member



Thanks alot! Your replies are always well "fleshed out" and gives me the opertunity to learn more, I like it :)

Well, I tried this:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /_/.+
RewriteRule ^/_/.+$ script_index.php [L]

RewriteCond %{THE_REQUEST} ^[A-Z]+\!/_/.+
RewriteRule!(\.(jpg¦gif¦css¦png¦ico)$) app_index.php [L]

but that gives a 404(?) when redirecting from "/_/o". I cannot understand why it would generate a 404 seeing as I thought I was rewriting every possible URL? Do you spot any errors here?

jdMorgan

6:05 pm on Jul 29, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The URI "seen" by RewriteRule in .htaccess is localized to the current directory (where the .htaccess file is), and so the Rule does not see the path to the current directory, only the path within the current directory or below it. This is a long way of saying that in your "/" directory, none of th URLs seen by RewriteRule will start with "/".

So your pattern should be "^_/." and not "/_/.+$" (You can leave off the "+$" in this case, because it's redundant).

However, the URLs seen by RewriteCond %{REQUEST_URI} are always the full path from root, so the leading slash is always needed in those patterns.

In the second rule's RewriteCond, the "!" for NOT is misplaced. It needs to be at the very beginning before the start anchor, and not in the middle of the pattern. This is because "!" is a mod_rewrite operator, and serves to negate the result of the completed regular-expressions evaluation. So, the pattern there should be:
!^[A-Z]+\ /_/.

Jim

chrisjoha

6:16 pm on Jul 29, 2005 (gmt 0)

10+ Year Member



Ah, of course! Heh, stupid errors on my behalf. It works now. Thanks alot!