Forum Moderators: phranque

Message Too Old, No Replies

single RewriteCond multiple RewriteRules

         

swamy_g

10:22 am on Jun 14, 2007 (gmt 0)

10+ Year Member



hi,
i have a problem with mod_rewrite, as you know, to prevent it from rewriting any files (.css, .gif etc) i used RewriteCond with!-f condition, but i have more than 1 rewrite rule.

This problem has already been discussed here
www.webmasterworld.com/forum92/1854.htm
but since the post is old, it is closed and i am not able to reply to it.

here's my .htacess

RewriteCond %{REQUESTFILENAME}!-d # is NOT a directory?
RewriteCond %{REQUESTFILENAME}!-f # is NOT a file?
RewriteRule ^(\w+)/?$ index.php?module=$1 [NC,QSA,L]
RewriteRule ^(products)/(\w+)/?$ index.php?module=$1&SYMBOL=$2 [NC,QSA]
RewriteRule ^(users)/(\w+)/?$ index.php?module=$1&user=$2 [NC,QSA]

So going by www.webmasterworld.com/forum92/1854.htm
i should reframe it as

RewriteCond %{REQUESTFILENAME} -d #is a directory?
RewriteCond %{REQUESTFILENAME} -f # is a file?
RewriteRule \.(gif¦jpg¦css)$ - [S=3]
#(or RewriteRule \.(gif¦jpg¦css)$ - [L])

RewriteRule ^(\w+)/?$ index.php?module=$1 [NC,QSA,L]
RewriteRule ^(products)/(\w+)/?$ index.php?module=$1&SYMBOL=$2 [NC,QSA]
RewriteRule ^(users)/(\w+)/?$ index.php?module=$1&user=$2 [NC,QSA]

But its not working for me... apache is still redirecting each and every .css and .gif files
Any help would be greatly appreciated

jdMorgan

6:04 pm on Jun 14, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The problem is one of Boolean logic:

The original code said:
If (NOT A) AND (NOT B)
Then execute rules

Where A and B are the conditions "directory exists" and "file exists."

The new code says, in part:
If (A) AND (B)
Then skip rules

The problem is that the second version, when taken as a whole, is not the logical opposite of the first.

The correct opposite (and correct solution), taking the new "is an image" condition into account is:
If (A) OR (B) OR (C)
Then skip rules

In other words, the only way your new RewriteRule will execute the "skip" is if the file exists *both* as a file and a directory --clearly an impossibility-- AND only if the filetype indicates an image -- which is not what you want.

Long story short, your code should be:


# If requested resource is an image file
RewriteCond $1 \.(gif¦jpg¦css)$ [OR]
# or if it exists as a directory
RewriteCond %{REQUEST_FILENAME} -d [OR]
# or if it exists as a file
RewriteCond %{REQUEST_FILENAME} -f
# then skip the next three rules
RewriteRule (.*) - [S=3]
#
# Following three rules processed only for non-image URLs which do not exist as real files or directories
RewriteRule ^(\w+)/?$ index.php?module=$1 [QSA,L]
RewriteRule ^(products)/(\w+)/?$ index.php?module=$1&SYMBOL=$2 [NC,QSA]
RewriteRule ^(users)/(\w+)/?$ index.php?module=$1&user=$2 [NC,QSA]

Note that since the "if image" logic had to be moved from the RewriteRule to a RewriteCond, I placed it first, so as to avoid the CPU-intensive "file exists" and "directory exists" checks for image requests.

I also removed the unnecessary [NC] flag from the second rule; Because no exact character matches are required by the pattern, [NC] is not needed.

Also be advised that using the regex "tokens" like "\w" does not seem to work on all platforms. The regular-expressions library is provided by the operating system, not the server. So if you contemplate changing servers or hosts at any time in the future, it would be best to avoid using them, and instead use the more-portable standard expressions.

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

Interestingly, the original theoretical work on derivation of logically-equivalent statements in positive (If) and negative (If NOT) logic systems is known as "DeMorgan's theorem"... :)

Jim