ChrisD
ChrisD

Reputation: 3518

Why is RewriteCond needed for this rule to work?

If I have the re-write rule:

RewriteRule ([^?]*) /script.php?path=$1 [L,QSA]

It will return a 500 internal error unless I also have the condition:

RewriteCond %{REQUEST_FILENAME} !-f

Why is this? I was under the impression that the conditions didn't actually change how the rule works but rather they were just exceptions to the rule.

Upvotes: 1

Views: 82

Answers (2)

Jon Lin
Jon Lin

Reputation: 143946

The -f tests if the given argument is a file and if it exists (it could be 0 bytes in size). The reason why you get a 500 internal server error is because the rewrite engine loops through all the rules until the URI stops changing. So for example, if all you had was this:

RewriteRule ([^?]*) /script.php?path=$1 [L,QSA]

And a request comes in as /foobar the URI is "foobar"

  1. "foobar" matches ([^?]*), URI gets rewritten as "/script.php?path=foobar"
  2. rewrite engine loops
  3. "script.php" matches ([^?]*), URI gets rewritten as "/script.php?path=script"
  4. rewrite engine loops
  5. etc.

Now if you add the condition:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([^?]*) /script.php?path=$1 [L,QSA]

And the request comes in as /foobar the URI is "foobar"

  1. "foobar" is not a file that exists, !-f is true
  2. "foobar" matches ([^?]*), URI gets rewritten as "/script.php?path=foobar"
  3. rewrite engine loops
  4. "script.php" is a file that exists, !-f is false
  5. condition is false so rule isn't applied. Rewriting stops, the resulting URI is "/script.php?path=foobar"

Upvotes: 2

anubhava
anubhava

Reputation: 786091

This is your rule:

RewriteRule ([^?]*) /script.php?path=$1 [L,QSA]

Here ([^?]*) matches 0 or more length of anything but ?. And then it rewrites it to /script.php URI. Resulting URI is injected again for evaluation. Please note that ([^?]*) will match again since it 0 or more of non-? and rule gets applied again. This looping goes on until mod_rewrite runs out of recursion limit (default=10).

Now when you have

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([^?]*) /script.php?path=$1 [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-f means apply next RewriteRule if request is not for a valid file.

Now after first rewrite the target URI /script.php is a valid file and RewriteCond fails this time and rule isn't applied again.

PS: This matching pattern ([^?]*) will ALWAYS match all URI patterns since REQUEST_URI can never contain a ?

You rule is equivalent of:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /script.php?path=$1 [L,QSA]

Upvotes: 1

Related Questions