Allow configuring showCause in ErrorHandler (#11587)
Allows to suppress "caused by" in error message, not only the stacks traces. ErrorHandler.showCause = false by default. Signed-off-by: Simone Bordet <simone.bordet@gmail.com> Co-authored-by: Dennis Hoersch <dennis.hoersch@springernature.com> Co-authored-by: Dennis Hoersch <dhs3000+ghtu@posteo.de>
This commit is contained in:
parent
0451bd4b86
commit
1b05d49fd8
|
@ -71,6 +71,7 @@ public class ErrorHandler implements Request.Handler
|
|||
public static final HttpField ERROR_CACHE_CONTROL = new PreEncodedHttpField(HttpHeader.CACHE_CONTROL, "must-revalidate,no-cache,no-store");
|
||||
|
||||
boolean _showStacks = false;
|
||||
boolean _showCauses = false;
|
||||
boolean _showMessageInTitle = true;
|
||||
String _defaultResponseMimeType = Type.TEXT_HTML.asString();
|
||||
HttpField _cacheControl = new PreEncodedHttpField(HttpHeader.CACHE_CONTROL, "must-revalidate,no-cache,no-store");
|
||||
|
@ -321,7 +322,7 @@ public class ErrorHandler implements Request.Handler
|
|||
htmlRow(writer, "URI", uri);
|
||||
htmlRow(writer, "STATUS", status);
|
||||
htmlRow(writer, "MESSAGE", message);
|
||||
while (cause != null)
|
||||
while (_showCauses && cause != null)
|
||||
{
|
||||
htmlRow(writer, "CAUSED BY", cause);
|
||||
cause = cause.getCause();
|
||||
|
@ -354,7 +355,7 @@ public class ErrorHandler implements Request.Handler
|
|||
writer.printf("URI: %s%n", request.getHttpURI());
|
||||
writer.printf("STATUS: %s%n", code);
|
||||
writer.printf("MESSAGE: %s%n", message);
|
||||
while (cause != null)
|
||||
while (_showCauses && cause != null)
|
||||
{
|
||||
writer.printf("CAUSED BY %s%n", cause);
|
||||
if (showStacks)
|
||||
|
@ -371,7 +372,7 @@ public class ErrorHandler implements Request.Handler
|
|||
json.put("status", Integer.toString(code));
|
||||
json.put("message", message);
|
||||
int c = 0;
|
||||
while (cause != null)
|
||||
while (_showCauses && cause != null)
|
||||
{
|
||||
json.put("cause" + c++, cause.toString());
|
||||
cause = cause.getCause();
|
||||
|
@ -458,6 +459,23 @@ public class ErrorHandler implements Request.Handler
|
|||
_showStacks = showStacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if exception causes are shown in the error pages
|
||||
*/
|
||||
@ManagedAttribute("Whether the error page shows the exception causes")
|
||||
public boolean isShowCauses()
|
||||
{
|
||||
return _showCauses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param showCauses True if exception causes are shown in the error pages
|
||||
*/
|
||||
public void setShowCauses(boolean showCauses)
|
||||
{
|
||||
_showCauses = showCauses;
|
||||
}
|
||||
|
||||
@ManagedAttribute("Whether the error message is shown in the error page title")
|
||||
public boolean isShowMessageInTitle()
|
||||
{
|
||||
|
|
|
@ -481,6 +481,82 @@ public class ErrorHandlerTest
|
|||
assertContent(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsNoStacksByDefault() throws Exception
|
||||
{
|
||||
String rawResponse = connector.getResponse("""
|
||||
GET /badmessage/444 HTTP/1.1
|
||||
Host: Localhost
|
||||
|
||||
""");
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat("Response status code", response.getStatus(), is(444));
|
||||
assertThat("Response Content-Length", response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0));
|
||||
assertThat(response.getContent(), not(containsString("<h3>Caused by:</h3>")));
|
||||
assertThat(response.getContent(), not(containsString("org.eclipse.jetty.server.ErrorHandlerTest$1.handle")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsStacksIfSpecified() throws Exception
|
||||
{
|
||||
ErrorHandler errorHandler = new ErrorHandler();
|
||||
errorHandler.setShowStacks(true);
|
||||
server.setErrorHandler(errorHandler);
|
||||
|
||||
String rawResponse = connector.getResponse("""
|
||||
GET /badmessage/444 HTTP/1.1
|
||||
Host: Localhost
|
||||
|
||||
""");
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat("Response status code", response.getStatus(), is(444));
|
||||
assertThat("Response Content-Length", response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0));
|
||||
assertThat(response.getContent(), containsString("<h3>Caused by:</h3>"));
|
||||
assertThat(response.getContent(), containsString("org.eclipse.jetty.server.ErrorHandlerTest$1.handle"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsNoCausesByDefault() throws Exception
|
||||
{
|
||||
String rawResponse = connector.getResponse("""
|
||||
GET /badmessage/444 HTTP/1.1
|
||||
Host: Localhost
|
||||
|
||||
""");
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat("Response status code", response.getStatus(), is(444));
|
||||
assertThat("Response Content-Length", response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0));
|
||||
assertThat(response.getContent(), not(containsString("<th>CAUSED BY:</th>")));
|
||||
assertThat(response.getContent(), not(containsString("<td>org.eclipse.jetty.http.BadMessageException: 444: null</td>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsCausesIfSpecified() throws Exception
|
||||
{
|
||||
ErrorHandler errorHandler = new ErrorHandler();
|
||||
errorHandler.setShowCauses(true);
|
||||
server.setErrorHandler(errorHandler);
|
||||
|
||||
String rawResponse = connector.getResponse("""
|
||||
GET /badmessage/444 HTTP/1.1
|
||||
Host: Localhost
|
||||
|
||||
""");
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat("Response status code", response.getStatus(), is(444));
|
||||
assertThat("Response Content-Length", response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0));
|
||||
assertThat(response.getContent(), containsString("<th>CAUSED BY:</th>"));
|
||||
assertThat(response.getContent(), containsString("<td>org.eclipse.jetty.http.BadMessageException: 444: null</td>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoBodyErrorHandler() throws Exception
|
||||
{
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.eclipse.jetty.io.Content;
|
|||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.Fields;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
@ -58,7 +60,7 @@ public class ServerHttpCookieTest
|
|||
_server.setHandler(new Handler.Abstract()
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Request request, Response response, Callback callback) throws Exception
|
||||
public boolean handle(Request request, Response response, Callback callback)
|
||||
{
|
||||
Fields parameters = Request.extractQueryParameters(request);
|
||||
Fields.Field setCookie = parameters.get("SetCookie");
|
||||
|
@ -79,11 +81,17 @@ public class ServerHttpCookieTest
|
|||
}
|
||||
});
|
||||
HttpConnectionFactory httpConnectionFactory = _connector.getConnectionFactory(HttpConnectionFactory.class);
|
||||
httpConnectionFactory.setRecordHttpComplianceViolations(true);
|
||||
_httpConfiguration = httpConnectionFactory.getHttpConfiguration();
|
||||
_httpConfiguration.addComplianceViolationListener(new ComplianceViolation.LoggingListener());
|
||||
_server.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void afterEach()
|
||||
{
|
||||
LifeCycle.stop(_server);
|
||||
}
|
||||
|
||||
public static Stream<Arguments> requestCases()
|
||||
{
|
||||
return Stream.of(
|
||||
|
@ -101,7 +109,7 @@ public class ServerHttpCookieTest
|
|||
|
||||
// multiple cookie tests
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=value; other=extra", 200, "Version=", List.of("[name=value]", "[other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=value, other=extra", 400, null, List.of("BadMessageException", "Comma cookie separator").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=value, other=extra", 400, null, List.of("400", "Comma cookie separator").toArray(new String[0])),
|
||||
Arguments.of(from("RFC6265_STRICT,COMMA_SEPARATOR,"), "Cookie: name=value, other=extra", 200, "Version=", List.of("[name=value]", "[other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265, "Cookie: name=value, other=extra", 200, "name=value", null),
|
||||
Arguments.of(RFC6265_LEGACY, "Cookie: name=value, other=extra", 200, null, List.of("[name=value, other=extra]").toArray(new String[0])),
|
||||
|
@ -110,13 +118,13 @@ public class ServerHttpCookieTest
|
|||
Arguments.of(RFC2965_LEGACY, "Cookie: name=value, other=extra", 200, "Version=", List.of("[name=value]", "[other=extra]").toArray(new String[0])),
|
||||
|
||||
// white space
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name =value", 400, null, List.of("BadMessageException", "Bad Cookie name").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name =value", 400, null, List.of("400", "Bad Cookie name").toArray(new String[0])),
|
||||
Arguments.of(from("RFC6265,OPTIONAL_WHITE_SPACE"), "Cookie: name =value", 200, null, List.of("name=value").toArray(new String[0])),
|
||||
|
||||
// bad characters
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=va\\ue", 400, null, List.of("BadMessageException", "Bad Cookie value").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=va\\ue", 400, null, List.of("400", "Bad Cookie value").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=\"value\"", 200, "Version=", List.of("[name=value]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=\"value;other=extra\"", 400, null, List.of("BadMessageException", "Bad Cookie quoted value").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=\"value;other=extra\"", 400, null, List.of("400", "Bad Cookie quoted value").toArray(new String[0])),
|
||||
Arguments.of(RFC6265, "Cookie: name=\"value;other=extra\"", 200, "name=value", null),
|
||||
Arguments.of(RFC6265_LEGACY, "Cookie: name=\"value;other=extra\"", 200, null, List.of("[name=value;other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC2965, "Cookie: name=\"value;other=extra\"", 200, null, List.of("[name=value;other=extra]").toArray(new String[0])),
|
||||
|
|
|
@ -164,11 +164,7 @@ public class MultiPartServletTest
|
|||
}
|
||||
content.close();
|
||||
|
||||
assert400orEof(listener, responseContent ->
|
||||
{
|
||||
assertThat(responseContent, containsString("400: bad"));
|
||||
assertThat(responseContent, containsString("Form is larger than max length"));
|
||||
});
|
||||
assert400orEof(listener, responseContent -> assertThat(responseContent, containsString("400")));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
@ -203,11 +199,7 @@ public class MultiPartServletTest
|
|||
.body(multiPart)
|
||||
.send(listener);
|
||||
|
||||
assert400orEof(listener, responseContent ->
|
||||
{
|
||||
assertThat(responseContent, containsString("400: bad"));
|
||||
assertThat(responseContent, containsString("Form with too many keys"));
|
||||
});
|
||||
assert400orEof(listener, responseContent -> assertThat(responseContent, containsString("400")));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
@ -363,7 +355,6 @@ public class MultiPartServletTest
|
|||
.send();
|
||||
|
||||
assertEquals(400, response.getStatus());
|
||||
assertThat(response.getContentAsString(), containsString("max file size exceeded"));
|
||||
}
|
||||
|
||||
String[] fileList = tmpDir.toFile().list();
|
||||
|
|
Loading…
Reference in New Issue