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: [email protected]
For additional commands, e-mail: [email protected]