Forum Moderators: phranque

Message Too Old, No Replies

Custom 403-404-500 errors handling in .htaccess *except for images*!

How can I do this?

         

tata668

1:27 am on Sep 28, 2010 (gmt 0)

10+ Year Member



I'd like something like this in my .htaccess:


ErrorDocument 403 /error403.php
ErrorDocument 404 /error404.php
ErrorDocument 500 /error500.php


But not for files with a .jpg, .jpeg, .gif and .png extension!

A negative regex doesn't seem to work:


<FilesMatch !"\.(jpg|jpeg|gif|png)$">
ErrorDocument 403 /error403.php
ErrorDocument 404 /error404.php
ErrorDocument 500 /error500.php
</FilesMatch>


To resume, I want to be able to manage the 403-404-500 errors but NOT for the images. This is because I don't want every missing/blocked images to call a .php file!

Is there any way to do this?

Thanks in advance!

jdMorgan

2:14 pm on Sep 28, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You can override your custom error document declarations for image requests:

ErrorDocument 403 /error403.php
ErrorDocument 404 /error404.php
ErrorDocument 500 /error500.php
#
<FilesMatch "\.(gif|jpe?g|png|ico)$">
ErrorDocument 403 /small-image-or-blank-file.gif
ErrorDocument 404 /small-image-or-blank-file.gif
ErrorDocument 500 /small-image-or-blank-file.gif
</FilesMatch>

Alternately, you could just use the "error text" option for the directives in the last section. For example:

ErrorDocument 404 "No such image

Note that there is no closing quote when using this format. See
[httpd.apache.org...]

Jim

tata668

11:14 pm on Sep 28, 2010 (gmt 0)

10+ Year Member



Thanks for the reply jdMorgan!

I use something similar as what you suggest, but I still have a problem.

Let's take the 404 error and say I want all documents that contain "123" to go to /index.php, all the missing images to /image.php and the others missing files to /error.php

-----------------------

RewriteEngine On

ErrorDocument 404 /error.php

<FilesMatch "\.(gif|jpe?g|png|ico)$">
ErrorDocument 404 /image.php
</FilesMatch>

RewriteCond %{REQUEST_URI} \.(gif|jpe?g|png|ico)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ default [R=404,L]

RewriteCond %{REQUEST_URI} 123 [NC]
RewriteRule ^(.*)$ index.php [QSA,L]

-----------------------

I need the first RewriteRule because some images can contain "123" (ex: 1234.jpg)! But the "R=404" in this rule redirects to /error.php not to /image.php!

This simplified example shows exactly my problem: I want to return a default 403/404/500 error for images, knowing that some RewriteRule may apply to them if I do not manage them as soon as possible.

I think the workaround is to never use "ErrorDocument 404", but instead to manage 404 explicitly:

-----------------------

# NOT USED!:
# ErrorDocument 404 /error.php

# Images
RewriteCond %{REQUEST_URI} \.(gif|jpe?g|png|ico)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ default [R=404,L]

# Other files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ error.php [QSA]

-----------------------

What do you think?

jdMorgan

1:40 pm on Sep 30, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Your rules are inefficient and the syntax of the 404-image rule looks incorrect. It should not be necessary to do all these extremely-inefficient "exists" checks to solve your problem. Simply rewrite requests that meet all requirements to index.php, and let the non-existent images go 404 using the default server 404 mechanism.

With all corrections, the code should be:

# Declare default 404 error document
ErrorDocument 404 /error404.php
#
# Override default 404 error document for missing-image requests
<FilesMatch "\.(gif|jpe?g|png|ico)$">
ErrorDocument 404 /small-image-or-blank-file.gif
</FilesMatch>
#
# Rewrite all non-image requests containing "123" to index.php
RewriteCond %{REQUEST_URI} !\.(gif|jpe?g|png|ico)$ [NC]
RewriteRule 123 index.php [L]

In order to avoid server performance problems, you should avoid invoking filesystem checks and reverse-DNS lookups whenever possible.

Jim

tata668

10:40 pm on Sep 30, 2010 (gmt 0)

10+ Year Member



Pointing the images to /error.php was just a test to be able to debug the request (in my php editor) when a call to a missing image was done. What I really want is the missing images to return the default 404 error.

Also, the problem with what you suggest is that for every following RewriteRules (let's say I have 20 of them) I'll have to add "RewriteCond %{REQUEST_URI} !\.(gif|jpe?g|png|ico)$ [NC]" too, right?

I would prefere a way to remove the need to deal with the image requests as soon as I can!

Is that possible?

jdMorgan

1:31 am on Oct 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Also, the problem with what you suggest is that for every following RewriteRules (let's say I have 20 of them) I'll have to add "RewriteCond %{REQUEST_URI} !\.(gif|jpe?g|png|ico)$ [NC]" too, right?

Only if all 20 rules are also to be invoked for requested URLs containing "123".

Did you test the code I posted? If so, what are the remaining problems?

Jim

tata668

11:47 am on Oct 1, 2010 (gmt 0)

10+ Year Member



jdMorgan, thanks again for the help and for the tips to improve the performance.

Yes, I just tested your solution and indeed it works. But, as I say, I would like a way to not have to deal with the images in a RewriteCond for every RewriteRule I make.

But now, I just realised I have a bigger problem than that! Let's says I only use:

----------------

# Declare default 404 error document
ErrorDocument 404 /error.php

# Override default 404 error document for missing-image requests
<FilesMatch "\.(gif|jpe?g|png|ico)$">
ErrorDocument 404 /image.php
</FilesMatch>

----------------

If I call "/doesntexist.gif" it works: /image.php is called.

But if I call "/test/doesntexist.gif" it's /error.php that is called!

Why?!?

jdMorgan

12:36 pm on Oct 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



But, as I say, I would like a way to not have to deal with the images in a RewriteCond for every RewriteRule I make.

Let me re-state what I have already written: Unless every RewriteRule you make is also intended to rewrite URLs containing "123," you will not have to deal with the images in a RewriteCond for every RewriteRule you make.

And if this were the case, those additional rule would never execute anyway, because the first rule (the one posted here) would have already been invoked, and it would have rewritten the URL-path, causing those subsequent rules to fail to match.

If the problem is more complex that what you have described, then you still have the option of using a "skip rule" or a "quit rule" to either skip over rules (see RewriteRule [S] flag) or to terminate mod_rewrite execution (see RewriteRule [L] flag) if the request is for an image. You also may have the option to combine those 20 rules into one using a "local OR" in the RewriteRule pattern, or a "lookup table" construct where both the URL-path to be tested and the filepath to be substituted are placed in RewriteConds sharing a single RewriteRule -- and in this case, sharing a single RewriteCond to test for image filetypes at the top.

If you wish to discuss this point further, then please demonstrate some of these additional rules, as otherwise we'll waste a great deal of time trying to allay your fears about a probably-nonexistent problem.

If I call "/doesntexist.gif" it works: /image.php is called. But if I call "/test/doesntexist.gif" it's /error.php that is called! Why?!?

Since <FilesMatch> does not care about directory paths and looks only at the final path-part (the filename), this implies that some other rule or some other module is affecting these requests. If you are not using them, disable content-negotiation/MultiViews (see Apache core Options directive) and disable AcceptPathInfo (see Apache core, available on Apache 2.x only).

Also look for other Redirect, RedirectMatch, Alias, ScriptAlias, and RewriteRule directives in the server config files and .htaccess files that could be modifying the requested URL-path for /test/doesntexist.gif requests.

And do be sure to delete your browser cache before testing any new server-side code -- whether it's code in .htaccess files or in scripts. Forcing a reload is often not sufficient, so delete the cache.

Jim

tata668

4:25 pm on Oct 2, 2010 (gmt 0)

10+ Year Member



jdMorgan, again, thanks for this wonderful help!

If you don't mind let's first check the "doesntexist.gif" problem, it's the one that currently really driving me mad!

I'm using Apache 2.2.

Here's my httpd.conf, without the comments so it's easier to read: [pastebin.com...]

I have removed all .htaccess and cleared my Firefox cache (using the developper toolbar)

Here's error.php:

---------

<?php
file_put_contents("C:\\testApache.txt", time() . ' - ERROR - ' . $_SERVER['REQUEST_URI']);
---------

Here's image.php:

---------
<?php
file_put_contents("C:\\testApache.txt", time() . ' - IMAGE - ' . $_SERVER['REQUEST_URI']);
---------

When I call, using Firefox : hXXp://local.loc/doesntexist.gif
C:\testApache.txt contains:

---------

1286036207 - IMAGE - /doesntexist.gif
---------


When I call, using Firefox : hXXp://local.loc/test/doesntexist.gif
C:\testApache.txt contains:

---------

1286036121 - ERROR - /test/doesntexist.gif
---------


Any idea? I really don't understand...

jdMorgan

6:20 pm on Oct 2, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Due to time constraints, my ability to provide support is contingent upon your following the suggestions I have already posted. All help offered here is on a volunteer basis, and no-one is getting paid. Please see my previous post, implement the proposed solutions, and confirm that you have done so.

Jim

tata668

7:38 pm on Oct 2, 2010 (gmt 0)

10+ Year Member



Unfortunately what you suggested doesn't seem to fix my "doesntexist.gif" problem.

Thanks a lot anyway!