Apache's Errordocument Directive Does Not Redirect

Apache's ErrorDocument directive does not redirect

A few different mis-conceptions in the question. The following PHP code:

header("HTTP/1.0 500 Internal Server Error");
die();

Will never trigger an Apache error page - it's triggering your browser's default error page. Once control has been given over to PHP, it does not go back to Apache for error handling.

ErrorDocument only works for error codes, not success codes. It's in the docs

Syntax: ErrorDocument error-code document

http://httpd.apache.org/docs/current/mod/core.html#errordocument

If you were mistaking one kind of browser error page for a server error, then that might be the cause of your main problem too. Unless your custom error handler outputs a certain amount of data, some browsers will always show their own error pages. Make sure your output is at least a few kilobytes in size.

The cause of your problem is most likely just Apache's built-in behavior combined with your choice of test URLs. From the ErrorDocument docs:

Although most error messages can be
overriden, there are certain
circumstances where the internal
messages are used regardless of the
setting of ErrorDocument. In
particular, if a malformed request is
detected, normal request processing
will be immediately halted and the
internal error message returned. This
is necessary to guard against security
problems caused by bad requests.


Edit: How to simulate a 500 error in Apache. My first thought was syntax errors in .htaccess, but this wont trigger custom error handlers. The easiest way I found was to enable CGI in .htaccess by adding these lines:

ErrorDocument 500 /500.php
Options +ExecCGI
AddHandler cgi-script .pl

And then adding a perl script that crashes:

#!/usr/bin/perl
safasfdsfdd_(*EYFIUOBAF(_*AS^FD_(*AWHD{

You will need to make sure the perl script is executable by apache's user. This shows my custom 500 handler.

However, you're very unlikely to ever trigger an Apache 500 when using PHP, so this probably isn't a useful test.

Apache's ErrorDocument directive does not redirect

A few different mis-conceptions in the question. The following PHP code:

header("HTTP/1.0 500 Internal Server Error");
die();

Will never trigger an Apache error page - it's triggering your browser's default error page. Once control has been given over to PHP, it does not go back to Apache for error handling.

ErrorDocument only works for error codes, not success codes. It's in the docs

Syntax: ErrorDocument error-code document

http://httpd.apache.org/docs/current/mod/core.html#errordocument

If you were mistaking one kind of browser error page for a server error, then that might be the cause of your main problem too. Unless your custom error handler outputs a certain amount of data, some browsers will always show their own error pages. Make sure your output is at least a few kilobytes in size.

The cause of your problem is most likely just Apache's built-in behavior combined with your choice of test URLs. From the ErrorDocument docs:

Although most error messages can be
overriden, there are certain
circumstances where the internal
messages are used regardless of the
setting of ErrorDocument. In
particular, if a malformed request is
detected, normal request processing
will be immediately halted and the
internal error message returned. This
is necessary to guard against security
problems caused by bad requests.


Edit: How to simulate a 500 error in Apache. My first thought was syntax errors in .htaccess, but this wont trigger custom error handlers. The easiest way I found was to enable CGI in .htaccess by adding these lines:

ErrorDocument 500 /500.php
Options +ExecCGI
AddHandler cgi-script .pl

And then adding a perl script that crashes:

#!/usr/bin/perl
safasfdsfdd_(*EYFIUOBAF(_*AS^FD_(*AWHD{

You will need to make sure the perl script is executable by apache's user. This shows my custom 500 handler.

However, you're very unlikely to ever trigger an Apache 500 when using PHP, so this probably isn't a useful test.

local URL for apache ErrorDocument directive not working in .htaccess file

You probably found the solution to your problem since the time you asked, but for anyone having the same kind of issue, I would say the problem is that you are running your site with localhost.

The message says that Apache encountered a 404 error when trying to get the file specified for Errordocument 404, so it doesn't see

/404.php

I suggest you create a fake domain in your hosts file and set up a vhost with it.

Hosts on OSX :

sudo nano /etc/hosts

Hosts on Windows, Right-click this file to edit in administrator mode :

 C:\WINDOWS\System32\Drivers\Etc\Hosts

and enter something like this:

127.0.0.1 myfakedomain.com

To set up virtual hosts, you must uncomment the call to httpd-vhosts.conf in httpd.conf (near the end, using MAMP in this case)

# Virtual hosts
Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf

but the location of this file depends of the stack you are using (Wamp, Mamp, Xampp, etc) so search with the keyword "Virtual host" in its documentation.

Then you will be able to run your site using

myfakedomain.com/ 

in your browser and 404 errors should be handled the right way.

Single ErrorDocument directive to catch all errors (.htaccess)

That is not possible. You need to have a ErrorDocument directive for each status code you want to handle differently than with the default error handler.

Apache htaccess ErrorDocument directive not working

%00 or in Hex \x00 is a NULL byte. When web server finds a NULL byte at the end then web server thinks it is a spoofing request and considers it to be dangerous to be processed by any directives.

Due to security reasons web server doesn't load any modules for this request and returns a 404 / Not found status. Browser shows default 404 page with your decoded URL just below Not Found text.

Apache error Document automatic re-write rule

Don't use an absolute URL in the ErrorDocument directive

ErrorDocument 403 http://example.com/error/404

You shouldn't be using an absolute URL in the ErrorDocument directive to begin with! This will trigger a 302 response (ie. a 302 temporary redirect) to the target URL. So, this won't send a 403 (or 404) response back to the user-agent on the first response.

(This format of the ErrorDocument directive should only be used in very exceptional circumstances since you also lose a lot of information about the URL that triggered the response in the first place.)

To internally serve a custom error document on the same server, this should be a root-relative URL, starting with a slash (no scheme or hostname). For example:

ErrorDocument 403 /error/404

However, /error/404 is unlikely to be a valid end-point. This should represent a valid resource that can be served. eg. /error/404.html.

(And this naturally gets round the issue of having to specifying HTTP vs HTTPS.)



To answer your specific question...

because the above example if i use https ill have to hard code https

(Although, arguably, you should be HTTPS everywhere these days.)

However, to do what you are asking, you could do something like the following using the REQUEST_SCHEME server variable, for example:

ErrorDocument 403 %{REQUEST_SCHEME}://%{HTTP_HOST}/error/404

Or, if the REQUEST_SCHEME server variable is not available then you can construct this from the HTTPS server variable using mod_rewrite and assign this to an environment variable. For example:

RewriteEngine On
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ - [E=PROTO:http%1]

ErrorDocument 403 %{reqenv:PROTO}://%{HTTP_HOST}/error/404

The %1 backreference contains s when HTTPS is on and is empty otherwise. So the PROTO environment variable is set to either http or https.

This does assume that the SSL is managed by the application server and not a front-end proxy (like Cloudflare Flexible SSL etc.).

Custom 404 for selected URL without ErrorDocument

I am not looking for Errordocument like 404 or 403

Why not? That is exactly how you do this. There is no other way on Apache-only (without using another server-side script) to trigger a 404 HTTP status and serve a custom response.

For example:

ErrorDocument 404 /spoof404.txt

RewriteRule ^foo\.html$ - [NC,R=404]
RewriteRule ^hello$ - [NC,R=404]
RewriteRule ^file/example\.php$ - [NC,R=404]

When you request /foo.html it will trigger a 404 and /spoof404.txt will be served.

When specifying a status ode outside of the 3xx range, the substituion string is ignored (hence the use of a single - - hyphen). In this case, the L flag is also superfluous, since it is implied when specifying a non-3xx R code.


UPDATE:

how to block with parameters like example.com/something.php?something=tokens&othertoken=token

The RewriteRule directive matches against the URL-path only, to match the query string (everything after the first ?) then you need an additional condition (RewriteCond directive) and check against the QUERY_STRING server variable.

For example, to match that exact URL (although case-insensitively) and trigger a 404:

RewriteCond %{QUERY_STRING} ^something=tokens&othertoken=token$ [NC]
RewriteRule ^something\.php$ - [NC,R=404]


Related Topics



Leave a reply



Submit