This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit ff38fd5e7fe1c71e050382d25aaf9eab942985b8 Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Aug 16 15:57:31 2023 +0100 Use application provided status code for error page if present --- .../apache/catalina/core/StandardHostValve.java | 13 ++++--- .../catalina/core/TestStandardHostValve.java | 41 +++++++++++++++++++--- webapps/docs/changelog.xml | 10 ++++++ 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/java/org/apache/catalina/core/StandardHostValve.java b/java/org/apache/catalina/core/StandardHostValve.java index 3b3b316dae..a186dc2a53 100644 --- a/java/org/apache/catalina/core/StandardHostValve.java +++ b/java/org/apache/catalina/core/StandardHostValve.java @@ -294,11 +294,14 @@ final class StandardHostValve extends ValveBase { } } } else { - // A custom error-page has not been defined for the exception - // that was thrown during request processing. Check if an - // error-page for error code 500 was specified and if so, - // send that page back as the response. - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + /* + * A custom error-page has not been defined for the exception that was thrown during request processing. + * Set the status to 500 if an error status has not already been set and check for custom error-page for + * the status. + */ + if (response.getStatus() < HttpServletResponse.SC_BAD_REQUEST) { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } // The response is an error response.setError(); diff --git a/test/org/apache/catalina/core/TestStandardHostValve.java b/test/org/apache/catalina/core/TestStandardHostValve.java index 4fc629d2e9..db4b7ccc09 100644 --- a/test/org/apache/catalina/core/TestStandardHostValve.java +++ b/test/org/apache/catalina/core/TestStandardHostValve.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequestEvent; import jakarta.servlet.ServletRequestListener; @@ -39,19 +40,31 @@ import org.apache.tomcat.util.descriptor.web.ErrorPage; public class TestStandardHostValve extends TomcatBaseTest { + @Test + public void testErrorPageHandling400() throws Exception { + doTestErrorPageHandling(400, "", "/400"); + } + + + @Test + public void testErrorPageHandling400WithException() throws Exception { + doTestErrorPageHandling(400, "java.lang.IllegalStateException", "/400"); + } + + @Test public void testErrorPageHandling500() throws Exception { - doTestErrorPageHandling(500, "/500"); + doTestErrorPageHandling(500, "", "/500"); } @Test public void testErrorPageHandlingDefault() throws Exception { - doTestErrorPageHandling(501, "/default"); + doTestErrorPageHandling(501, "", "/default"); } - private void doTestErrorPageHandling(int error, String report) + private void doTestErrorPageHandling(int error, String exception, String report) throws Exception { // Set up a container @@ -68,6 +81,12 @@ public class TestStandardHostValve extends TomcatBaseTest { Tomcat.addServlet(ctx, "report", new ReportServlet()); ctx.addServletMappingDecoded("/report/*", "report"); + // Add the handling for 400 responses + ErrorPage errorPage400 = new ErrorPage(); + errorPage400.setErrorCode(Response.SC_BAD_REQUEST); + errorPage400.setLocation("/report/400"); + ctx.addErrorPage(errorPage400); + // And the handling for 500 responses ErrorPage errorPage500 = new ErrorPage(); errorPage500.setErrorCode(Response.SC_INTERNAL_SERVER_ERROR); @@ -83,8 +102,8 @@ public class TestStandardHostValve extends TomcatBaseTest { // Request a page that triggers an error ByteChunk bc = new ByteChunk(); - int rc = getUrl("http://localhost:" + getPort() + - "/error?errorCode=" + error, bc, null); + int rc = getUrl("http://localhost:" + getPort() + "/error?errorCode=" + error + "&exception=" + exception, + bc, null); Assert.assertEquals(error, rc); Assert.assertEquals(report, bc.toString()); @@ -200,6 +219,18 @@ public class TestStandardHostValve extends TomcatBaseTest { throws ServletException, IOException { int error = Integer.parseInt(req.getParameter("errorCode")); resp.sendError(error); + + Throwable t = null; + String exception = req.getParameter("exception"); + if (exception != null && exception.length() > 0) { + try { + t = (Throwable) Class.forName(exception).getConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + // Should never happen but in case it does... + t = new IllegalArgumentException(); + } + req.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t); + } } } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 69f1e9e66f..4e00911021 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -105,6 +105,16 @@ issues do not "pop up" wrt. others). --> <section name="Tomcat 10.1.13 (schultz)" rtext="in development"> + <subsection name="Catalina"> + <changelog> + <fix> + If an application or library sets both a non-500 error code and the + <code>jakarta.servlet.error.exception</code> request attribute, use the + provided error code during error page processing rather than assuming an + error code of 500. (markt) + </fix> + </changelog> + </subsection> </section> <section name="Tomcat 10.1.12 (markt)" rtext="2023-08-14"> <subsection name="Catalina"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org