I was trying to setup mod_rewrite rules for a CakePHP app running under Apache.
According to the mod_rewrite docs, REQUEST_FILENAME
is “The full local filesystem path to the file or script matching the request.”
If that were true, this idiom, which I’ve seen in a number of places,
should work to prevent the RewriteRule
underneath it from firing when a request is made for a file which exists in the filesystem:
RewriteCond %{REQUEST_FILENAME} !-f
But it doesn’t. Looking at the rewrite log reveals that REQUEST_FILENAME
, on my system at least, is not the full filesystem path; it is actually relative to the document root. Which means that the condition is never true and the rewrite will always happen.
So in order to get it to work, I have to do this ugly hack:
RewriteCond /home/y/share/htdocs%{REQUEST_FILENAME} !-f
Why?
Did you ever find the solution to this? I’m having the same problem with a rewrite thing I’m doing at the moment..
cheers,
Jonathan.
Looks like -f is context sensitive, I just ran into this problem, when used in .htaccess or inside a tag, it works correctly, outside it has the same behaviour as %{REQUEST_URI}, so:
DocumentRoot “C:Site”
ServerName http://www.mysite.com
Will behave badly, however:
DocumentRoot “C:Site”
ServerName http://www.mysite.com
Will work as it’s supposed to.
Thanks
—
Craig “FrostyCoolSlug” McLure
Disregard my previous comment, seems that some cached stuff was causing confusion on the page..
A more simple solution, when looking at your example, change:
RewriteCond %{REQUEST_FILENAME} !-f
To read:
RewriteCond %{DOCUMENTROOT}%{REQUESTFILENAME} !-f
Thus getting a Document Root prefix. It is still context specific, so if you use .htaccess you don’t need %{DOCUMENT_ROOT} but from what i’ve seen, it shouldn’t go in , my apologies for any confusion.
Your rule works fine, Frosty. However, if you are using Alias’ed resources and wish to do the “-f” test, you’re back in the same boat. 🙁
It seems Apache doesn’t know how to check to see if a file exists when it’s being referenced via an alias.
When detecting if a file actually exists, you must use REQUEST_FILENAME, which corresponds to the file on your system. For most other things, use REQUEST_URI which corresponds to the directory and file name portion (URI) of the requested web address (URL).
Hi folks,
FrostySlug, your first answer (putting the directory tag around the rewrite) worked great for me!
Thanks!
Just to follow up on this that the reply by FrostySlug is correct (for FreeBSD anyway that had this problem) however his DOCUMENT_ROOT and REQUEST_FILENAME need the underscores in the middle to work – so DOCUMENT ‘underscore’ ROOT and REQUEST ‘underscore’ FILENAME
The alias occurs after the rewritecond checks for files and directories, so rewritecond -f doesn’t know about your aliased directory. I’ve looked for a way around this, but all solutions involve some convoluted regex for an apache file-system path + file. Ideally there would be some flag asking Apache to process the alias before the rewrite rules (this might cause problems with putting rewrite inside constructs though).
For me this didn’t help like sayd before:
DocumentRoot “C:Siteâ€
ServerName http://www.mysite.com
RewriteEngine On
Order allow,deny
Allow from all
RewriteCond $1 (^/images/)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /admin$1 [QSA,L]
But this did:
DocumentRoot “C:Siteâ€
ServerName http://www.mysite.com
Order allow,deny
Allow from all
RewriteEngine On
RewriteCond $1 (^/images/)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /admin$1 [QSA,L]
… putting everything concerning rewrite inside Directory.
Use `RewriteBase /` otherwise relative paths will be used.
you must define RewriteBase
It depends on what APACHE u are using.
Please see a difference between these two docs:
http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
“REQUEST_FILENAME
The full local filesystem path to the file or script matching the request.”
http://httpd.apache.org/docs/current/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.”
I think you are using a virtual host, like almost everyone. So like another person said, you have to use %{DOCUMENT_ROOT}%{REQUEST_FILENAME} instead of just %{REQUEST_FILENAME}