views:

51

answers:

3

Hi all,

This seems so simple, but I can't figure it out... I would like all requests to be rewritten to index.php (which will interpret the request) apart from 404.html which should be rewritten directly to 404.php.

The following code does work at rewriting everything to index.php, but 404.php never gets triggered.

I have left line 3 commented because I don't know what it does.

Options +FollowSymlinks
RewriteEngine on
#RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^404.html$ 404.php [L]
RewriteRule ^(.*)$ index.php  [QSA]

As you can see, my needs are very simple, but so is my brain! Please help!

Thanks.

EDIT

This line works fine on its own:

RewriteRule ^404.html$ 404.php

but when the other RewriteRule is introduced, everything gets forced through index.php - even 404.html...... (I tried changing the order too).

+1  A: 

You can invert the result of a match with prepend it with !. So:

RewriteRule ^404\.html$ 404.php
RewriteRule !^404\.html$ index.php [QSA]

This will match any request that’s path is not matched by ^404\.html$.

You might need to add the condition that is commented out:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^404\.html$ index.php [QSA]

Now this rule will only match if the request can additionally not be mapped onto an existing file.

Gumbo
I don't understand how this helps - I do want 404.html to be rewritten to 404.php ... and everything else to index.php with the requesnt as a query string.
Greg
@Greg: Fixed that.
Gumbo
@Gumbo: hmm, using what you put, requesting 404.html still gets directed to index.php ... what am I doing wrong?
Greg
@Greg: I guess you need to extend the second rule not to match existing files. Because otherwise `404.php` will also be matched.
Gumbo
A: 

I suggest this solution:

Options +FollowSymlinks
RewriteEngine on
#RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^404.html$ 404.php [L]
RewriteRule ^(.*)$ index.php  [QSA]

I believe the issue is that you are rewriting the URL to 404.php, then sending it to index.php. Putting [L] after the first rule will instruct the rewrite engine to not continue rewriting.

Raskolnikov
accessing 404.html still gets redirected through index.php! What am I missing???
Greg
A: 

This was driving me MAD! but I found the answer, for those who are getting confused like I was.

Look at line 4:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^404.html$ 404.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php

Taken from: easymodrewrite:

The [L] flag can have unexpected results if you are not clear on how the module behaves. Note that the following only applies when mod_rewrite is used in a .htaccess file. The [L] flag behaves exactly as expected when used in httpd.conf.

The L flag will tell Apache to stop processing the rewrite rules for that request. Now what is often unrealised is that it now makes a new request for the new, rewritten filename and begin processing the rewrite rules again.


Basically, you have to tell the second rule not to match existing files (404.php is a real file, not dynamic).

Hope this helps someone.

Greg