| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ======================================================================== |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| |
| [[custom-error-pages]] |
| === Creating Custom Error Pages |
| |
| The following sections describe several ways to create custom error pages in Jetty. |
| |
| ==== Defining error pages in web.xml |
| |
| You can use the standard webapp configuration file located in `webapp/WEB-INF/web.xml` to map errors to specific URLs with the `error-page` element. |
| This element creates a mapping between the error-code or exception-type to the location of a resource in the web application. |
| |
| * `error-code` - an integer value |
| * `exception-type` - a fully qualified class name of a Java Exception type |
| * `location` - location of the resource in the webapp relative to the root of the web application. Value should start with `/`. |
| |
| Error code example: |
| |
| [source, xml, subs="{sub-order}"] |
| ---- |
| <error-page> |
| <error-code>404</error-code> |
| <location>/jspsnoop/ERROR/404</location> |
| </error-page> |
| |
| ---- |
| |
| Exception example: |
| |
| [source, xml, subs="{sub-order}"] |
| ---- |
| <error-page> |
| <exception-type>java.io.IOException</exception-type> |
| <location>/jspsnoop/IOException</location> |
| </error-page> |
| |
| ---- |
| |
| The error page mappings created with the error-page element will redirect to a normal URL within the web application and will be handled as a normal request to that location and thus may be static content, a JSP or a filter and/or servlet. |
| When handling a request generated by an error redirection, the following request attributes are set and are available to generate dynamic content: |
| |
| javax.servlet.error.exception:: |
| The exception instance that caused the error (or null). |
| javax.servlet.error.exception_type:: |
| The class name of the exception instance that caused the error (or null). |
| javax.servlet.error.message:: |
| The error message. |
| javax.servlet.error.request_uri:: |
| The URI of the request with an error. |
| javax.servlet.error.servlet_name:: |
| The Servlet name of the servlet that the request was |
| dispatched to. |
| javax.servlet.error.status_code:: |
| The status code of the error (e.g. 404, 500 etc.). |
| |
| ==== Configuring error pages context files |
| |
| You can use context IoC XML files to configure the default error page mappings with more flexibility than is available with `web.xml`, specifically with the support of error code ranges. |
| Context files are normally located in `${jetty.base}/webapps/` (see `DeployerManager` for more details) and an example of more flexible error page mapping is below: |
| |
| [source, xml, subs="{sub-order}"] |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.eclipse.org/configure.dtd"> |
| |
| <Configure class="org.eclipse.jetty.webapp.WebAppContext"> |
| <Set name="contextPath">/test</Set> |
| <Set name="war"> |
| <SystemProperty name="jetty.base" default="."/>/webapps/test |
| </Set> |
| |
| <!-- by Code --> |
| <Get name="errorHandler"> |
| <Call name="addErrorPage"> |
| <Arg type="int">404</Arg> |
| <Arg type="String">/jspsnoop/ERROR/404</Arg> |
| </Call> |
| </Get> |
| |
| <!-- by Exception --> |
| <Get name="errorHandler"> |
| <Call name="addErrorPage"> |
| <Arg> |
| <Call class="java.lang.Class" name="forName"> |
| <Arg type="String">java.io.IOException</Arg> |
| </Call> |
| </Arg> |
| <Arg type="String">/jspsnoop/IOException</Arg> |
| </Call> |
| </Get> |
| |
| <!-- by Code Range --> |
| <Get name="errorHandler"> |
| <Call name="addErrorPage"> |
| <Arg type="int">500</Arg> |
| <Arg type="int">599</Arg> |
| <Arg type="String">/dump/errorCodeRangeMapping</Arg> |
| </Call> |
| </Get> |
| </Configure> |
| |
| ---- |
| |
| ==== Custom ErrorHandler class |
| |
| If no error page mapping is defined, or if the error page resource itself has an error, then the error page will be generated by an instance of `ErrorHandler` configured either the Context or the Server. |
| An `ErrorHandler` may extend the `ErrorHandler` class and may totally replace the handle method to generate an error page, or it can implement some or all of the following methods to partially modify the error pages: |
| |
| [source, java, subs="{sub-order}"] |
| ---- |
| void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException |
| void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message) throws IOException |
| void writeErrorPage(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks) throws IOException |
| void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, String message) throws IOException |
| void writeErrorPageBody(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks) throws IOException |
| void writeErrorPageMessage(HttpServletRequest request, Writer writer, int code, String message, String uri) throws IOException |
| void writeErrorPageStacks(HttpServletRequest request, Writer writer) throws IOException |
| ---- |
| |
| An `ErrorHandler` instance may be set on a Context by calling the `ContextHandler.setErrorHandler` method. This can be done by embedded code or via context IoC XML. |
| For example: |
| |
| [source, xml, subs="{sub-order}"] |
| ---- |
| <Configure class="org.eclipse.jetty.server.handler.ContextHandler"> |
| ... |
| <Set name="errorHandler"> |
| <New class="com.acme.handler.MyErrorHandler"/> |
| </Set> |
| ... |
| </Configure> |
| ---- |
| |
| An `ErrorHandler` instance may be set on the entire server by setting it as a dependent bean on the Server instance. |
| This can be done by calling `Server.addBean(Object)` via embedded code or in `jetty.xml` IoC XML: |
| |
| [source, xml, subs="{sub-order}"] |
| ---- |
| <Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| ... |
| <Call name="addBean"> |
| <Arg> |
| <New class="com.acme.handler.MyErrorHandler"/> |
| </Arg> |
| </Call> |
| ... |
| </Configure> |
| ---- |
| |
| ==== Server level 404 error |
| |
| It is possible to get a 'page not found' when a request is made to the server for a resource that is outside of any registered contexts. |
| As an example, you have a domain name pointing to your public server IP, yet no context is registered with Jetty to serve pages for that domain. |
| As a consequence, the server, by default, gives a listing of all contexts running on the server. |
| |
| One of the quickest ways to avoid this behavior is to create a catch all context. |
| Create a "root" web app mapped to the "/" URI, and use the `index.html` redirect to whatever place with a header directive. |