Mod_rewrite REQUEST_FILENAME doesn’t contain absolute path

apache-2.2mod-rewrite

I have a problem with a file test operation in a mod_rewrite RewriteCond entry which is testing whether %{REQUEST_FILENAME} exists. It seems that rather than %{REQUEST_FILENAME} being an absolute path, I'm getting a path which is rooted at the DocumentRoot instead.

Configuration

I have this inside a <VirtualHost> block in my apache 2.2.9 configuration:

RewriteEngine on
RewriteLog /tmp/rewrite.log
RewriteLogLevel 5

#push virtually everything through our dispatcher script
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/([^/]*)/?([^/]*) /dispatch.php?_c=$1&_m=$2 [qsa,L]

Diagnostics attempted

That rule is a common enough idiom for routing requests for non-existent files or directories through a script. Trouble is, it's firing even if a file does exist.

If I remove the rule, I can request normal files just fine. But with the rule in place, these requests get directed to dispatch.php

Rewrite log trace

Here's what I see in the rewrite.log

init rewrite engine with requested uri /test.txt
applying pattern '^/([^/]*)/?([^/]*)' to uri '/test.txt'
RewriteCond: input='/test.txt' pattern='!-f' => matched
RewriteCond: input='/test.txt' pattern='!-d' => matched
rewrite '/test.txt' -> '/dispatch.php?_c=test.txt&_m='
split uri=/dispatch.php?_c=test.txt&_m= -> uri=/dispatch.php, args=_c=test.txt&_m=
local path result: /dispatch.php
prefixed with document_root to /path/to/my/public_html/dispatch.php
go-ahead with /path/to/my/public_html/dispatch.php [OK]

So, it looks to me like the REQUEST_FILENAME is being presented as a path from the document root, rather than the file system root, which is presumably why the file test operator fails.

Any pointers for resolving this gratefully received…

Best Answer

Took me a while to find out as well, but the reason is mentioned in the mod_rewrite documentation:

REQUEST_FILENAME The full local filesystem path to the file or script matching the request, if this has already been determined by the server at the time REQUEST_FILENAME is referenced. Otherwise, such as when used in virtual host context, the same value as REQUEST_URI.

That's why it works in .htaccess but not in the conf file of the vhost. (And that's also why adding the DOCUMENT_ROOT works around the problem).