RewriteCond seems to fail


#1

I want to use a php script to handle URL errors. So I read
http://p2p.wrox.com/moderated-pro-php/29820-database-driven-clean-urls-apache-mod_rewrite.html
which recommends the following:

# If the REQUEST_FILENAME does not exist as a file or directory RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d RewriteRule ^(.*) /index.php?%{QUERY_STRING} [L]
(to make it work, I had to remove the “/” in the last line)

It fails bizarrely. It rewrites most names, even those of actual files. But not all. The name http://physpics.com/images/BlueNext.png is NOT rewritten, but the name …/BlueGNext.png is rewritten. The two files have identical read permissions.

My question: Why is this rule altering the names of actual existing files??? Why is the !-f ignored?


#2

Both seem to work with me, on your website. Could be in your end, maybe your browser has cached something.


#3

Since both of those files exist, it seems to work as intended. Try loading a file that doesn’t exist and you’ll be redirected in index.php


#4

Sorry, I should have been more clear.
The redirection affected all files, so I had to turn it off.
Everything is working at present.

For testing I now have a directory with its own .htaccess.
Request

This page exists, but the RewriteRule instead returns errorpage.php (in that same directory).
Both pages exhibit the entire /other/.htaccess file for reference.
So the question is:

Why is it not possible to get page /other/testpage.php?

A cache somewhere may have had an impact on the images;
the image that was loaded correctly is used in many pages;
the other is seldom used. I’ve put both in testpage and errorpage
and both are working.

The .htaccess file:

[code]RewriteEngine On

if directory, and if it has index.php, use it

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f
RewriteRule ^(.*) %{REQUEST_FILENAME}/index.php?%{QUERY_STRING} [L]

if directory, and if it has index.html, use it

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.html -f
RewriteRule ^(.*) %{REQUEST_FILENAME}/index.html?%{QUERY_STRING} [L]

if request non-existent file.html and file.php exists, use the latter

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.*).html$ $1.php [L]

supposed to catch only requests for non-existent pages or directories

instead it redirects almost all requests

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule ^(.*) errorpage.php?%{DOCUMENT_ROOT}%{REQUEST_FILENAME} [L][/code]


#5

Hmm, let me see if I understand what you are trying to do. You have various directories, some of which have index.html, some have index.php, and some have both (so .php is preferred), and some have none at all? But your REQUEST_FILENAME actually represents a directory with an index.php inside (%{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php) ? It seems terribly complex.

Anyway, one thing you may want to consider is the order of the requests. The last should probably be the first to catch all non existing files/directories first.

As it’s written, it won’t catch your request for http://physpics.com/other/testpage.php. I think you want the third set to catch it, right? But the rewrite rule is looking for something with .html at the end, then appending .php to the part before it. Your request is already .php.

To be honest, I’m not quite sure what you are trying to do.


#6

Okay, let’s keep it simple. The .htaccess below fails.
There IS a page http://physpics.com/other/testpage.php.
It has a green background.
But with the .htaccess below, the page retrieved is errorpage.php.
It has a red/purple background.

Why? How do I fix it?

.htaccess

[code]#http://p2p.wrox.com/moderated-pro-php/29820-database-driven-clean-urls-apache-mod_rewrite.html

RewriteEngine On

supposed to catch only requests for non-existent pages or directories

instead it redirects valid URLs to errorpage.pgp

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule ^(.*) errorpage.php?%{DOCUMENT_ROOT}%{REQUEST_FILENAME} [L]
[/code]


#7

Do you have a .htaccess file with rewriting rules in the root-directory? If so, it may interfere.


#8

Yes, I had the rules that were in the long version of the page for /other/
Now I have commented them out. And the problem persists.


#9

I don’t understand exactly what you mean. But, ok, I have another example you may try - it works by directing everything not a file or directory to index.php:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-s
Rewriterule (.*) index.php


#10

try

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) errorpage.php?$1

I’m assuming you want the requested file to be the query string? I don’t know why you have DOCUMENT_ROOT, and I think you don’t need a closing %

There’s a great site called askapache that has just about every htaccess trick you would ever want to use with working examples.


#11

Kerfluffel!

The construction %{DOCUMENT_ROOT}%{REQUEST_FILENAME} is garbage.
REQUEST_FILENAME is already in file system format.
So my RewriteConds were testing
/home/physpics/physpics.com/home/physpics/physpics.com/other/textpage.php
which is not a file, nor a directory. The condition will always fail.

Thanks for your help.

The correct rules are below.
Note that the first two sets are needed because the fourth set tests for a directory
and we want to be sure to have processed the default cases first.

[CODE]

if directory, and if it has index.php, use it

RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.php -f
RewriteRule ^(.*) %{REQUEST_FILENAME}/index.php [L]

if directory, and if it has index.html, use it

RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.html -f
RewriteRule ^(.*) %{REQUEST_FILENAME}/index.html?%{QUERY_STRING} [L]

if want non-existent file.html and file.php exists, use the latter

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.*).html$ $1.php [L]

# If the REQUEST_FILENAME does not exist as a file or directory
# http://p2p.wrox.com/moderated-pro-php/
#    29820-database-driven-clean-urls-apache-mod_rewrite.html

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) /test/testpage.php?%{REQUEST_FILENAME} [L]
[/CODE]