Apache2 mod_rewrite and %{REQUEST_FILENAME}
Filed Under (Sysadmin, Tips) by Amandine on 23-02-2010
I’m trying to develop a new website to increase my php object oriented skills. For this new website, I want every request for any url that doesn’t match a actual file on the disk to be redirected to index.php (to handle parameters in fact). Easy with apache2 rewrite rules :
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^/(.*)$ /index.php?rt=$1 [L,QSA]
This means : if the requested file is not a real file, and isn’t a directory, and isn’t a symlink, then redirect to index.php.
I was really surprised to discover that it doesn’t work. Though, everybody seems to use this syntax ! I checked my apache version : Apache/2.2.9 (Debian), nothing special with this one I guess.
To understand what Apache was doing with my rewrites, I activated the rewrite log :
RewriteLogLevel 5
Here’s what I got (the interesting part, cause I got a looot more !) :
[blah blah blah] (3) applying pattern '^/(.*)$' to uri '/toto.htm'
[blah blah blah] (4) RewriteCond: input='/toto.htm' pattern='!-f' => matched
[blah blah blah] (4) RewriteCond: input='/toto.htm' pattern='!-d' => matched
[blah blah blah] (4) RewriteCond: input='/toto.htm' pattern='!-l' => matched
[blah blah blah] (2) rewrite '/toto.htm' -> '/index.php?rt=toto.htm'
So apaches verifies only ‘/toto.htm’ and not the whole path for “%{REQUEST_FILENAME}”? I thought though it was the whole path… let’s verify in the doc.
From http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html, by habit (cause I used apache 2.0 a lot more than apache 2.2 from now on) :
REQUEST_FILENAME : The full local filesystem path to the file or script matching the request.
Hmm. But I use apache version 2.2, so what do they say here http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html :
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.
Ow.
REQUEST_URI : The resource requested in the HTTP request line. (In the example above, this would be “/index.html”.)
Ok, I understand, I use virtual hosts (like everybody, uh?), so the real syntax for my needs is :
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-l
RewriteRule ^/(.*)$ /index.php?rt=$1 [L,QSA]
This works even if it doubles the “/” between each variable (one / at the end of DOCUMENT_ROOT, and another at the beginning of REQUEST_FILENAME).
Here’s the rewrite log showing that it works :
[blah blah blah] (3) applying pattern '^/(.*)$' to uri '/toto.htm'
[blah blah blah] (4) RewriteCond: input='/path/to/documentroot//toto.htm' pattern='!-f' => not-matched
[blah blah blah] (1) pass through /toto.htm
Now I can disable this log if I want to keep space on my disk.
I must admit I read the description for REQUEST_FILENAME in apache2.2 several times before noticing that it was just the answer… too used to read too fast! Thanks to this old post that made me re-read slower ! ;)
Similar Posts:
- Apache2 Rewritemap
- URL redirections
- SSL Private Key file recovery
- Add disk space to a .img disk image (for use with xen for example)
- More loop devices

Haha.
Rewrite rules are magical, but can quickly become as complicated as hell.
See you soon in the train… Some day?
Alex from Maizières ;)
Thank you man..
I lost 4 hours of my day to solve these problems….
Stupid mod_rewrite…..
u, good sir, rock. thx!!!!