Creating custom error pages using Apache is easy. Simply put

ErrorDocument 404 /errors/404.html

in your vhost-config or .htaccess and apache will serve your file instead of that ugly default message.

However, when you use a static file, requests to /errors/404.html will now result in your error page being displayed with HTTP 200 OK status. I did not want it to end up in some search engine's directory, but unfortunately the files have to live inside the DocumentRoot so it can't simply be moved away. An obvious solution would have been to create a suitable entry in robots.txt:

User-Agent: *
Disallow: /errors/

However this still does not fix the fundamental problem of the file being accessible as a document - so how do I make it seem to the clients as if there was no such file in the first place?

In the case of the ErrorDocument being a script, it can just always output a 404 status code header. For static files? To my surprise mod_rewrite has no flag to reply with arbitrary status codes (or reply with 404 as [F] does for 403 Forbidden). My first hope was to use mod_alias' Redirect:

Redirect 404 /errors/404.html

This works, but will also be applied when Apache looks for the ErrorDocument itself, resulting in broken 404 pages. So is there a way to do a conditional redirect only if the request isn't the result of a 404? Turns out, there is: Apache sets the environment variable REDIRECT_STATUS for you. So this is what I currently use:

RewriteCond %{ENV:REDIRECT_STATUS} !=404
RewriteRule ^errors/404\.html$ thisfiledoesnotexist [L]

This will effectively trigger a 404 error (because the file this redirects to does not exist) and when Apache fetches the ErrorDocument, no redirect happens.

Now, while this works its certainly not elegant. If anyone has a solution that does not rely on the file thisfiledoesnotexist not existing, I'd be happy to hear from you.

Previous Post Next Post