Handling HTTP errors with Apache and Tomcat using mod_jk

When you are working with web server in frontend (Apache in this example) and backend application servers (Tomcat here), you may wish to customize your error pages depending on the HTTP error code returned (either from the web server or application server).

Pre-requisites

For the following example, you will need as pre-requisites at least those versions:

  • Web Server Apache >= 2.2.x
  • Mod JK >= 1.2.27 (rule extensions are not available in earlier versions)

Apache configuration

If you want to handle any error coming from your web server or from your application servers, you will need to perform some changes in your configuration to allow the handling. First of all you will need to set up some parameters in your Apache configuration file (in apache2.conf file directly or in your VirtualHost definitions).

In my example, I am handling any HTTP error code between:

  • HTTP 400 and HTTP 405
  • HTTP 500 and 504

I am using an only file (written in PHP) allowing me to send back a simple HTML page to the user depending on the HTTP error code received.

Here is what I’ve configured in my apache2.conf file for handling any error listed above:

ErrorDocument 400 /errorhandler.php?error=400
ErrorDocument 401 /errorhandler.php?error=401
ErrorDocument 402 /errorhandler.php?error=402
ErrorDocument 403 /errorhandler.php?error=403
ErrorDocument 404 /errorhandler.php?error=404
ErrorDocument 405 /errorhandler.php?error=405
ErrorDocument 500 /errorhandler.php?error=500
ErrorDocument 501 /errorhandler.php?error=501
ErrorDocument 502 /errorhandler.php?error=502
ErrorDocument 503 /errorhandler.php?error=503
ErrorDocument 504 /errorhandler.php?error=504

The errorhandler.php file could be like that (feel free to customize it as you want with a beautiful CSS theme, for the example I’ve used a basic configuration ;)):

The HTTP request could not be understood by the server due to malformed syntax.
The web browser may be too recent, or the HTTP server may be too old.";
        }
        if($_GET['error']=='401'){
                $errorcode = "Error 401";
                $errormessage = "The request requires user authentication.
This means that all or a part of the requested server is protected by a password that should be given to the server to allow access to its contents.";
        }
        if($_GET['error']=='402'){
                $errorcode = "Error 402";
                $errormessage = "Payment Required
";
        }
        if($_GET['error']=='403'){
                $errorcode = "Error 403";
                $errormessage = "The HTTP server understood the request, but is refusing to fulfill it.
This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable (for example the server is an Intranet and only the LAN machines are authorized to connect).";
        }
        if($_GET['error']=='404'){
                $errorcode = "Error 404";
                $errormessage = "The server has not found anything matching the requested address (URI) ( not found ).
This means the URL you have typed or cliked on is wrong or obsolete and does not match any document existing on the server (you may try to gradualy remove the URL components from the right to the left to eventualy retrieve an existing path).";
        }
        if($_GET['error']=='405'){
                $errorcode = "Error 405";
                $errormessage = "This code is given with the Allow header and indicates that the method used by the client is not supported for this URI.
";
        }
        if($_GET['error']=='500'){
                $errorcode = "Error 500";
                $errormessage = "The HTTP server encountered an unexpected condition which prevented it from fulfilling the request.
For example this error can be caused by a serveur misconfiguration, or a resource exhausted or denied to the server on the host machine.";
        }
        if($_GET['error']=='501'){
                $errorcode = "Error 501";
                $errormessage = "The HTTP server does not support the functionality required to fulfill the request.
This is the appropriate response when the server does not recognize the request method and is not capable of supporting it for any resource (either the web browser is too recent, or the HTTP server is too old).";
        }
        if($_GET['error']=='502'){
                $errorcode = "Error 502";
                $errormessage = "The gateway server returned an invalid response.
The HTTP server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request.";
        }
        if($_GET['error']=='503'){
                $errorcode = "Error 503";
                $errormessage = "The HTTP server is currently unable to handle the request due to a temporary overloading or maintenance of the server.
The implication is that this is a temporary condition which will be alleviated after some delay.";
        }
        if($_GET['error']=='504'){
                $errorcode = "Error 504";
                $errormessage = "This response is like 408 (Request Time-out) except that a gateway or proxy has timed out.
";
        }
}
else {
        $errorcode = "Error";
        $errormessage = "An error has occured while trying to contact the website. Please contact support.";
}
?>


mod_jk configuration

Once you’re done with the main configuration of Apache, you will have to specify to Apache that you want to handle any HTTP error coming from the application servers. For that, you will have to use the rule extension use_server_errors when mounting an access point to a worker through mod_jk.

By default, for a mounting point you are using:

JkMount /myapp/* worker1

But if you want to handle any HTTP 40x error coming from this worker, you will have to add the use_server_errors extension to your mounting point:

# Use web server error page for any error
JkMount /myapp/* worker1;use_server_errors=400

To handle any HTTP 50x error:

# Use web server error page only for technical errors
JkMount /myapp/* worker1;use_server_errors=500

Or another option to handle both errors using just one command:

JkMount /myapp/* worker1;use_server_errors=400,500

You are now handling any error received from your application server with your web server allowing you to customize it as you want.

Feel free to read more about this rule extension on the official website.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *