2

I want to implement a custom Error 400 page on my website tikolu.net, to a file called 400.php in a folder called error.

The first thing I tried was to simply place ErrorDocument 400 /error/400.php into my .htaccess file. This doesn't work because for errors like 400, it cannot be handled by the .htaccess file and instead must be placed into the httpd.conf file, as mentioned here.

This works in the sense of being acknowledged by Apache, but it still does not fully work. The default message still displays, but this time with this added at the bottom: Additionally, a 400 Bad Request error was encountered while trying to use an ErrorDocument to handle the request.

This is because ErrorDocument does not redirect, but instead just rewrites the URL, while now trying to show 400.php. But because this is just a rewrite, Apache still thinks that the requested document was the same one which initially caused the error, so it results in an Error 400 again.

The furthest I managed to get is instead say ErrorDocument 400 https://tikolu.net/error/400.php. This works because Apache cannot rewrite the URL again (as it is an external one), and is forced to redirect. However, this won't work for me as I need to know the original URL which caused the error. I tried getting $_SERVER["HTTP_REFERER"] from PHP but it is empty.

The ErrorDocument directive has access to some variables, like REDIRECT_URL but they are only set if the target is internal, so it wouldn't work in this case.

Is there a possibility to use ErrorDocument but with a proper redirect, so that it can be handled by a PHP script, without repeating the error? If not, is there a way to use the directive's variables when being redirected to an external location?


Here are the contents of my .htaccess file:

RewriteEngine On
IndexOptions +Charset=UTF-8

# REMOVE www FROM URL
<If "%{HTTP_HOST} == 'www.tikolu.net'">
    RedirectMatch (.*) https://tikolu.net$1
</If>

# REDIRECT HTTP TO HTTPS
<If "%{HTTPS} == 'off'">
    RedirectMatch (.*) https://tikolu.net$1
</If>

# BLOCK .listing FILE
<Files ~ "\.listing$">
    Require all denied
</Files>

# DIRECTORY INDEXES
DirectoryIndex index.php index.html

# ERROR DOCUMENTS
ErrorDocument 404 /error/404.php
ErrorDocument 403 /error/403.php

# REDIRECTS

(various redirects follow, all in the form RewriteRule location$ /destination [L])

I have disabled my .htaccess file temporarily (by renaming it), and the problem still remains.


EDIT: I managed to find a slightly hacky (but working) workaround:

ErrorDocument 400 '<meta http-equiv="refresh" content="0; URL=/error/400.php">'

Tikolu
  • 21
  • 3
  • How are you triggering the 400 response? What other directives do you have? "But because this is just a rewrite, Apache still thinks that the requested document was the same one which initially caused the error, so it results in an Error 400 again." - this isn't true. `400.php` is called via an _internal subrequest_ (not strictly a "rewrite", but similar). This triggers another internal request. If you are getting that additional message, then it would seem that the request to `400.php` is itself triggering a 400 error. – MrWhite Aug 02 '20 at 14:15
  • Check Apache's error log. – Michael Hampton Aug 02 '20 at 14:28
  • `ErrorDocument 400 400.php` - The target URL needs a slash prefix, otherwise it will be seen as literal text and it will simply output the string "400.php". – MrWhite Aug 02 '20 at 14:37
  • @MrWhite I'm triggering the 400 error by going to an invalid URL like `https://example.com/%`. I know that the target URL needs a prefix, I just used `400.php` as an example. In reality I say something like `ErrorDocument 400 /var/www/html/example.com/public_html/400.php`, and I can confirm doing exactly this, but for a 404, works. – Tikolu Aug 02 '20 at 15:10
  • and "What other directives do you have?" An error like this is often due to conflicts with other directives. Are you not using vHosts? FWIW, I have this working OK on my system. `/%` triggers the custom `ErrorDocument` defined in a vHost. I'm also using a URL-path relative to the document root, rather than absolute filesystem path. (The docs don't actually state that a filesystem path is permitted here?) Have you checked the error log, as Michael suggested? – MrWhite Aug 02 '20 at 17:01
  • That's the access log, not the error log. Check the error log. – Michael Hampton Aug 02 '20 at 19:39
  • @MrWhite this is the only vHost on my system, and the only other `ErrorDocument` directive's are for 404 and 403, in my `.htaccess` file. – Tikolu Aug 02 '20 at 19:41
  • @MichaelHampton The error log under `/var/log/apache2/error.log` doesn't mention the 400 error anywhere, I don't know am I checking it wrong or if there's another log that I am unaware of. The `access.log`, however, just states that /% was accessed, with no mention of the 400 error. – Tikolu Aug 02 '20 at 20:01
  • And you have no other directives... mod_rewrite, mod_alias, etc. in your vHost or `.htaccess` file(s)? – MrWhite Aug 02 '20 at 21:20
  • @MrWhite I have a few `RewriteRule`s configured in my `.htaccess`, but that's pretty much it. – Tikolu Aug 03 '20 at 01:31
  • Do you mind sharing the contents of your `.htaccess` file (please edit your question to add this information). Right now that is the most probable cause, so needs to be ruled out at least. Did you also try using a document-root relative URL-path in the `ErrorDocument` directive? – MrWhite Aug 03 '20 at 08:54
  • 1
    @MrWhite I've edited the answer to show my `.htaccess` file. I have tried a document-root relative URL path for the `ErrorDocument`, and everything is still the same. – Tikolu Aug 03 '20 at 13:15
  • "slightly hacky (but working) workaround" - and presumably you get the _requested_ URL from the `Referer` in this case? You seem to have covered all bases - I'm out of ideas. What platform and version of Apache 2.4 are you using? I only have access to Apache 2.4.7 on Windows to test at the moment (which, as I mentioned above, "works" in this regard). This could well be platform dependent as the OS certainly has an effect on how requests are mapped to the filesystem. – MrWhite Aug 04 '20 at 17:31

0 Answers0