Author: markt Date: Wed Feb 14 10:17:19 2018 New Revision: 1824210 URL: http://svn.apache.org/viewvc?rev=1824210&view=rev Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=41007 Add the ability to specify static HTML responses for specific error codes and/or exception types with the ErrorReportValve.
Modified: tomcat/trunk/java/org/apache/catalina/util/ErrorPageSupport.java tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties tomcat/trunk/webapps/docs/changelog.xml tomcat/trunk/webapps/docs/config/valve.xml Modified: tomcat/trunk/java/org/apache/catalina/util/ErrorPageSupport.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/ErrorPageSupport.java?rev=1824210&r1=1824209&r2=1824210&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/util/ErrorPageSupport.java (original) +++ tomcat/trunk/java/org/apache/catalina/util/ErrorPageSupport.java Wed Feb 14 10:17:19 2018 @@ -68,11 +68,7 @@ public class ErrorPageSupport { * * @return The ErrorPage for the named exception type, or {@code null} if * none is configured - * - * @deprecated Unused. Will be removed in Tomcat 10. - * Use {@link #find(Throwable)} instead. */ - @Deprecated public ErrorPage find(String exceptionType) { return exceptionPages.get(exceptionType); } Modified: tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java?rev=1824210&r1=1824209&r2=1824210&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java (original) +++ tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java Wed Feb 14 10:17:19 2018 @@ -16,7 +16,11 @@ */ package org.apache.catalina.valves; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.Writer; import java.util.Scanner; import java.util.concurrent.atomic.AtomicBoolean; @@ -27,10 +31,13 @@ import javax.servlet.http.HttpServletRes import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; +import org.apache.catalina.util.ErrorPageSupport; +import org.apache.catalina.util.IOTools; import org.apache.catalina.util.ServerInfo; import org.apache.catalina.util.TomcatCSS; import org.apache.coyote.ActionCode; import org.apache.tomcat.util.ExceptionUtils; +import org.apache.tomcat.util.descriptor.web.ErrorPage; import org.apache.tomcat.util.res.StringManager; import org.apache.tomcat.util.security.Escape; @@ -54,7 +61,11 @@ public class ErrorReportValve extends Va private boolean showServerInfo = true; + private final ErrorPageSupport errorPageSupport = new ErrorPageSupport(); + + //------------------------------------------------------ Constructor + public ErrorReportValve() { super(true); } @@ -159,6 +170,27 @@ public class ErrorReportValve extends Va return; } + ErrorPage errorPage = null; + if (throwable != null) { + errorPage = errorPageSupport.find(throwable); + } + if (errorPage == null) { + errorPage = errorPageSupport.find(statusCode); + } + if (errorPage == null) { + // Default error page + errorPage = errorPageSupport.find(0); + } + + + if (errorPage != null) { + if (sendErrorPage(errorPage.getLocation(), response)) { + // If the page was sent successfully, don't write the standard + // error page. + return; + } + } + String message = Escape.htmlElementContent(response.getMessage()); if (message == null) { if (throwable != null) { @@ -322,6 +354,37 @@ public class ErrorReportValve extends Va return trace.toString(); } + + private boolean sendErrorPage(String location, Response response) { + File file = new File(location); + if (!file.isAbsolute()) { + file = new File(getContainer().getCatalinaBase(), location); + } + if (!file.isFile() || !file.canRead()) { + getContainer().getLogger().warn( + sm.getString("errorReportValve.errorPageNotFound", location)); + return false; + } + + // Hard coded for now. Consider making this optional. At Valve level or + // page level? + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); + + try { + OutputStream os = response.getOutputStream(); + InputStream is = new FileInputStream(file); + IOTools.flow(is, os); + } catch (IOException e) { + getContainer().getLogger().warn( + sm.getString("errorReportValve.errorPageIOException", location), e); + return false; + } + + return true; + } + + /** * Enables/Disables full error reports * @@ -347,4 +410,48 @@ public class ErrorReportValve extends Va public boolean isShowServerInfo() { return showServerInfo; } + + + public boolean setProperty(String name, String value) { + if (name.startsWith("errorCode.")) { + int code = Integer.parseInt(name.substring(10)); + ErrorPage ep = new ErrorPage(); + ep.setErrorCode(code); + ep.setLocation(value); + errorPageSupport.add(ep); + return true; + } else if (name.startsWith("exceptionType.")) { + String className = name.substring(14); + ErrorPage ep = new ErrorPage(); + ep.setExceptionType(className); + ep.setLocation(value); + errorPageSupport.add(ep); + return true; + } + return false; + } + + public String getProperty(String name) { + String result; + if (name.startsWith("errorCode.")) { + int code = Integer.parseInt(name.substring(10)); + ErrorPage ep = errorPageSupport.find(code); + if (ep == null) { + result = null; + } else { + result = ep.getLocation(); + } + } else if (name.startsWith("exceptionType.")) { + String className = name.substring(14); + ErrorPage ep = errorPageSupport.find(className); + if (ep == null) { + result = null; + } else { + result = ep.getLocation(); + } + } else { + result = null; + } + return result; + } } Modified: tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties?rev=1824210&r1=1824209&r2=1824210&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties Wed Feb 14 10:17:19 2018 @@ -43,6 +43,8 @@ errorReportValve.note=Note errorReportValve.rootCauseInLogs=The full stack trace of the root cause is available in the server logs. errorReportValve.unknownReason=Unknown Reason errorReportValve.noDescription=No description available +errorReportValve.errorPageIOException=Unable to display error page at [{0}] due to an exception +errorReportValve.errorPageNotFound=Unable to find a static error page at [{0}] # Remote IP valve remoteIpValve.invalidPortHeader=Invalid value [{0}] found for port in HTTP header [{1}] Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1824210&r1=1824209&r2=1824210&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Wed Feb 14 10:17:19 2018 @@ -55,6 +55,11 @@ application provided error handling and/or the container provided error handling (<code>ErrorReportValve</code>) as appropriate. (markt) </add> + <add> + <bug>41007</bug>: Add the ability to specify static HTML responses for + specific error codes and/or exception types with the + <code>ErrorReportValve</code>. (markt) + </add> </changelog> </subsection> <subsection name="Coyote"> Modified: tomcat/trunk/webapps/docs/config/valve.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=1824210&r1=1824209&r2=1824210&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/valve.xml (original) +++ tomcat/trunk/webapps/docs/config/valve.xml Wed Feb 14 10:17:19 2018 @@ -1710,10 +1710,13 @@ <subsection name="Introduction"> <p>The <strong>Error Report Valve</strong> is a simple error handler - for HTTP status codes that will generate and return HTML error pages.</p> + for HTTP status codes that will generate and return HTML error pages. It can + also be configured to return pre-defined static HTML pages for specific + status codes and/or exception types.</p> <p><strong>NOTE:</strong> Disabling both showServerInfo and showReport will - only return the HTTP status code and remove all CSS.</p> + only return the HTTP status code and remove all CSS from the default + response.</p> </subsection> @@ -1730,6 +1733,31 @@ default error report valve.</p> </attribute> + <attribute name="errorCode.nnn" required="false"> + <p>The location of the UTF-8 encoded HTML file to return for the HTTP + error code represented by <code>nnn</code>. For example, + <code>errorCode.404</code> specifies the file to return for an HTTP 404 + error. The location may be relative or absolule. If relative, it must be + relative to <code>$CATALINA_BASE</code>. The special value of + <code>errorCode.0</code> may be used to define a default error page to + be used if no error page is defined for a status code. If no matching + error page is found, the default <strong>Error Report Valve</strong> + response will be returned.</p> + </attribute> + + <attribute name="exceptionType.fullyQualifiedClassName" required="false"> + <p>The location of the UTF-8 encoded HTML file to return if an error has + occurred and the <code>javax.servlet.error.exception</code> request + attribute has been set to an instance of + <code>fullyQualifiedClassName</code> or a sub-class of it. For example, + <code>errorCode.java.io.IOException</code> specifies the file to return + for an <code>IOException</code>. The location may be relative or + absolule. If relative, it must be relative to + <code>$CATALINA_BASE</code>. If no matching error page is found, the + default <strong>Error Report Valve</strong> response will be + returned.</p> + </attribute> + <attribute name="showReport" required="false"> <p>Flag to determine if the error report is presented when an error occurs. If set to <code>false</code>, then the error report is not in --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org