You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2022/03/15 20:52:26 UTC

[tomcat] branch 8.5.x updated: Backport errorCode.nnn handling to 8.5.x

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/8.5.x by this push:
     new 2366a69  Backport errorCode.nnn handling to 8.5.x
2366a69 is described below

commit 2366a695507aa261fdada21ca4072faa57319fa2
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Feb 14 10:17:19 2018 +0000

    Backport errorCode.nnn handling to 8.5.x
    
    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.
---
 .../org/apache/catalina/util/ErrorPageSupport.java |   4 -
 .../apache/catalina/valves/ErrorReportValve.java   | 107 +++++++++++++++++++++
 .../apache/catalina/valves/LocalStrings.properties |   2 +
 .../catalina/valves/LocalStrings_fr.properties     |   2 +
 .../catalina/valves/LocalStrings_ja.properties     |   2 +
 .../catalina/valves/LocalStrings_ko.properties     |   2 +
 .../catalina/valves/LocalStrings_zh_CN.properties  |   2 +
 webapps/docs/changelog.xml                         |   9 ++
 webapps/docs/config/valve.xml                      |  29 +++++-
 9 files changed, 154 insertions(+), 5 deletions(-)

diff --git a/java/org/apache/catalina/util/ErrorPageSupport.java b/java/org/apache/catalina/util/ErrorPageSupport.java
index 0a241e8..19ebba7 100644
--- a/java/org/apache/catalina/util/ErrorPageSupport.java
+++ b/java/org/apache/catalina/util/ErrorPageSupport.java
@@ -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);
     }
diff --git a/java/org/apache/catalina/valves/ErrorReportValve.java b/java/org/apache/catalina/valves/ErrorReportValve.java
index 74ccc1f..ae02d62 100644
--- a/java/org/apache/catalina/valves/ErrorReportValve.java
+++ b/java/org/apache/catalina/valves/ErrorReportValve.java
@@ -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.HttpServletResponse;
 
 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 ValveBase {
 
     private boolean showServerInfo = true;
 
+    private final ErrorPageSupport errorPageSupport = new ErrorPageSupport();
+
+
     //------------------------------------------------------ Constructor
+
     public ErrorReportValve() {
         super(true);
     }
@@ -168,6 +179,27 @@ public class ErrorReportValve extends ValveBase {
             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) {
@@ -331,6 +363,37 @@ public class ErrorReportValve extends ValveBase {
         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
      *
@@ -356,4 +419,48 @@ public class ErrorReportValve extends ValveBase {
     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;
+    }
 }
diff --git a/java/org/apache/catalina/valves/LocalStrings.properties b/java/org/apache/catalina/valves/LocalStrings.properties
index b7f38fc..a144166 100644
--- a/java/org/apache/catalina/valves/LocalStrings.properties
+++ b/java/org/apache/catalina/valves/LocalStrings.properties
@@ -27,6 +27,8 @@ accessLogValve.unsupportedEncoding=Failed to set encoding to [{0}], will use the
 accessLogValve.writeFail=Failed to write log message [{0}]
 
 errorReportValve.description=Description
+errorReportValve.errorPageIOException=Unable to display error page at [{0}] due to an exception
+errorReportValve.errorPageNotFound=Unable to find a static error page at [{0}]
 errorReportValve.exception=Exception
 errorReportValve.exceptionReport=Exception Report
 errorReportValve.message=Message
diff --git a/java/org/apache/catalina/valves/LocalStrings_fr.properties b/java/org/apache/catalina/valves/LocalStrings_fr.properties
index bafd479..01eb334 100644
--- a/java/org/apache/catalina/valves/LocalStrings_fr.properties
+++ b/java/org/apache/catalina/valves/LocalStrings_fr.properties
@@ -27,6 +27,8 @@ accessLogValve.unsupportedEncoding=Impossible de changer l''encodage en [{0}], l
 accessLogValve.writeFail=Impossible d''écrire le message de log [{0}]
 
 errorReportValve.description=description
+errorReportValve.errorPageIOException=Impossible d''afficher la page d''erreur à [{0}] à cause d''une exception
+errorReportValve.errorPageNotFound=Impossible de trouver une erreur page statique à [{0}]
 errorReportValve.exception=exception
 errorReportValve.exceptionReport=Rapport d'exception
 errorReportValve.message=message
diff --git a/java/org/apache/catalina/valves/LocalStrings_ja.properties b/java/org/apache/catalina/valves/LocalStrings_ja.properties
index a04dca2..94004bf 100644
--- a/java/org/apache/catalina/valves/LocalStrings_ja.properties
+++ b/java/org/apache/catalina/valves/LocalStrings_ja.properties
@@ -27,6 +27,8 @@ accessLogValve.unsupportedEncoding=文字エンコーディングに [{0}] を
 accessLogValve.writeFail=ログメッセージ [{0}] の書き込みに失敗しました
 
 errorReportValve.description=説明
+errorReportValve.errorPageIOException=例外のため [{0}] にエラーページを表示できません
+errorReportValve.errorPageNotFound=[{0}]に静的エラーページが見つかりません。
 errorReportValve.exception=例外
 errorReportValve.exceptionReport=例外報告
 errorReportValve.message=メッセージ
diff --git a/java/org/apache/catalina/valves/LocalStrings_ko.properties b/java/org/apache/catalina/valves/LocalStrings_ko.properties
index bd8918f..55502ce 100644
--- a/java/org/apache/catalina/valves/LocalStrings_ko.properties
+++ b/java/org/apache/catalina/valves/LocalStrings_ko.properties
@@ -27,6 +27,8 @@ accessLogValve.unsupportedEncoding=인코딩을 [{0}](으)로 설정하지 못
 accessLogValve.writeFail=다음 로그 메시지를 쓰지 못했습니다: [{0}]
 
 errorReportValve.description=설명
+errorReportValve.errorPageIOException=예외 발생으로 인하여 [{0}]에 위치한 오류 페이지를 표시할 수 없습니다.
+errorReportValve.errorPageNotFound=[{0}]에 위치한 정적 오류 페이지를 찾을 수 없습니다.
 errorReportValve.exception=예외
 errorReportValve.exceptionReport=예외 보고
 errorReportValve.message=메시지
diff --git a/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties b/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties
index 063525d..15b734d 100644
--- a/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties
+++ b/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties
@@ -27,6 +27,8 @@ accessLogValve.unsupportedEncoding=未能将编码设置为[{0}],将使用系
 accessLogValve.writeFail=无法写入日志消息[{0}]
 
 errorReportValve.description=描述
+errorReportValve.errorPageIOException=由于出现异常,无法在[{0}]处显示错误页
+errorReportValve.errorPageNotFound=在[{0}]无法找到静态错误页面
 errorReportValve.exception=例外情况
 errorReportValve.exceptionReport=异常报告
 errorReportValve.message=消息
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index dc71da6..f1deb1c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -105,6 +105,15 @@
   issues do not "pop up" wrt. others).
 -->
 <section name="Tomcat 8.5.78 (schultz)" rtext="in development">
+  <subsection name="Catalina">
+    <changelog>
+      <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="Web applications">
     <changelog>
       <fix>
diff --git a/webapps/docs/config/valve.xml b/webapps/docs/config/valve.xml
index 04760d9..ee9bdf4 100644
--- a/webapps/docs/config/valve.xml
+++ b/webapps/docs/config/valve.xml
@@ -2103,7 +2103,9 @@
   <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.</p>
@@ -2123,6 +2125,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 (custom error message and/or
            stack trace) is presented when an error occurs. If set to

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org