Use application provided status code for error page if present
diff --git a/java/org/apache/catalina/core/StandardHostValve.java b/java/org/apache/catalina/core/StandardHostValve.java
index b7aaad0..7d5b890 100644
--- a/java/org/apache/catalina/core/StandardHostValve.java
+++ b/java/org/apache/catalina/core/StandardHostValve.java
@@ -309,11 +309,14 @@
}
}
} 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 99d82f3..efd3a4a 100644
--- a/test/org/apache/catalina/core/TestStandardHostValve.java
+++ b/test/org/apache/catalina/core/TestStandardHostValve.java
@@ -20,6 +20,7 @@
import java.util.ArrayList;
import java.util.List;
+import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
@@ -40,18 +41,30 @@
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 @@
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 @@
// 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 @@
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 88cbeb8..f828cba 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 9.0.80 (remm)" 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 9.0.79 (remm)" rtext="2023-08-15">
<subsection name="Catalina">