Commit a30740f8 authored by Scott Frederick's avatar Scott Frederick

Separate server properties for message and errors

Prior to this commit, there was a property server.error.include-details
that allowed configuration of the message and errors attributes in a
server error response.

This commit separates the control of the message and errors attributes
into two separate properties named server.error.include-message and
server.error.include-binding-errors. When the message attribute is
excluded from a servlet response, the value is changed from a
hard-coded text value to an empty value.

Fixes gh-20505
parent 18a9a229
......@@ -53,26 +53,38 @@ public class ManagementErrorEndpoint {
@RequestMapping("${server.error.path:${error.path:/error}}")
@ResponseBody
public Map<String, Object> invoke(ServletWebRequest request) {
return this.errorAttributes.getErrorAttributes(request, includeStackTrace(request), includeDetails(request));
return this.errorAttributes.getErrorAttributes(request, includeStackTrace(request), includeMessage(request),
includeBindingErrors(request));
}
private boolean includeStackTrace(ServletWebRequest request) {
switch (this.errorProperties.getIncludeStacktrace()) {
case ALWAYS:
return true;
case ON_TRACE_PARAM:
case ON_PARAM:
return getBooleanParameter(request, "trace");
default:
return false;
}
}
private boolean includeDetails(ServletWebRequest request) {
switch (this.errorProperties.getIncludeDetails()) {
private boolean includeMessage(ServletWebRequest request) {
switch (this.errorProperties.getIncludeMessage()) {
case ALWAYS:
return true;
case ON_DETAILS_PARAM:
return getBooleanParameter(request, "details");
case ON_PARAM:
return getBooleanParameter(request, "message");
default:
return false;
}
}
private boolean includeBindingErrors(ServletWebRequest request) {
switch (this.errorProperties.getIncludeBindingErrors()) {
case ALWAYS:
return true;
case ON_PARAM:
return getBooleanParameter(request, "errors");
default:
return false;
}
......
......@@ -51,16 +51,16 @@ class ManagementErrorEndpointTests {
void errorResponseNeverDetails() {
ManagementErrorEndpoint endpoint = new ManagementErrorEndpoint(this.errorAttributes, this.errorProperties);
Map<String, Object> response = endpoint.invoke(new ServletWebRequest(new MockHttpServletRequest()));
assertThat(response).containsEntry("message", "An error occurred while processing the request");
assertThat(response).containsEntry("message", "");
assertThat(response).doesNotContainKey("trace");
}
@Test
void errorResponseAlwaysDetails() {
this.errorProperties.setIncludeStacktrace(ErrorProperties.IncludeStacktrace.ALWAYS);
this.errorProperties.setIncludeDetails(ErrorProperties.IncludeDetails.ALWAYS);
this.errorProperties.setIncludeMessage(ErrorProperties.IncludeAttribute.ALWAYS);
this.request.addParameter("trace", "false");
this.request.addParameter("details", "false");
this.request.addParameter("message", "false");
ManagementErrorEndpoint endpoint = new ManagementErrorEndpoint(this.errorAttributes, this.errorProperties);
Map<String, Object> response = endpoint.invoke(new ServletWebRequest(this.request));
assertThat(response).containsEntry("message", "test exception");
......@@ -70,20 +70,20 @@ class ManagementErrorEndpointTests {
@Test
void errorResponseParamsAbsent() {
this.errorProperties.setIncludeStacktrace(ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM);
this.errorProperties.setIncludeDetails(ErrorProperties.IncludeDetails.ON_DETAILS_PARAM);
this.errorProperties.setIncludeStacktrace(ErrorProperties.IncludeStacktrace.ON_PARAM);
this.errorProperties.setIncludeMessage(ErrorProperties.IncludeAttribute.ON_PARAM);
ManagementErrorEndpoint endpoint = new ManagementErrorEndpoint(this.errorAttributes, this.errorProperties);
Map<String, Object> response = endpoint.invoke(new ServletWebRequest(this.request));
assertThat(response).containsEntry("message", "An error occurred while processing the request");
assertThat(response).containsEntry("message", "");
assertThat(response).doesNotContainKey("trace");
}
@Test
void errorResponseParamsTrue() {
this.errorProperties.setIncludeStacktrace(ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM);
this.errorProperties.setIncludeDetails(ErrorProperties.IncludeDetails.ON_DETAILS_PARAM);
this.errorProperties.setIncludeStacktrace(ErrorProperties.IncludeStacktrace.ON_PARAM);
this.errorProperties.setIncludeMessage(ErrorProperties.IncludeAttribute.ON_PARAM);
this.request.addParameter("trace", "true");
this.request.addParameter("details", "true");
this.request.addParameter("message", "true");
ManagementErrorEndpoint endpoint = new ManagementErrorEndpoint(this.errorAttributes, this.errorProperties);
Map<String, Object> response = endpoint.invoke(new ServletWebRequest(this.request));
assertThat(response).containsEntry("message", "test exception");
......@@ -93,13 +93,13 @@ class ManagementErrorEndpointTests {
@Test
void errorResponseParamsFalse() {
this.errorProperties.setIncludeStacktrace(ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM);
this.errorProperties.setIncludeDetails(ErrorProperties.IncludeDetails.ON_DETAILS_PARAM);
this.errorProperties.setIncludeStacktrace(ErrorProperties.IncludeStacktrace.ON_PARAM);
this.errorProperties.setIncludeMessage(ErrorProperties.IncludeAttribute.ON_PARAM);
this.request.addParameter("trace", "false");
this.request.addParameter("details", "false");
this.request.addParameter("message", "false");
ManagementErrorEndpoint endpoint = new ManagementErrorEndpoint(this.errorAttributes, this.errorProperties);
Map<String, Object> response = endpoint.invoke(new ServletWebRequest(this.request));
assertThat(response).containsEntry("message", "An error occurred while processing the request");
assertThat(response).containsEntry("message", "");
assertThat(response).doesNotContainKey("trace");
}
......
......@@ -67,14 +67,14 @@ class WebMvcEndpointChildContextConfigurationIntegrationTests {
ClientResponse response = client.get().uri("actuator/fail").accept(MediaType.APPLICATION_JSON).exchange()
.block();
Map<Object, Object> body = response.bodyToMono(Map.class).block();
assertThat(body).containsEntry("message", "An error occurred while processing the request");
assertThat(body).containsEntry("message", "");
assertThat(body).doesNotContainKey("trace");
});
}
@Test
void errorPageAndErrorControllerIncludeDetails() {
this.runner.withPropertyValues("server.error.include-stacktrace=always", "server.error.include-details=always")
this.runner.withPropertyValues("server.error.include-stacktrace=always", "server.error.include-message=always")
.run((context) -> {
String port = context.getEnvironment().getProperty("local.management.port");
WebClient client = WebClient.create("http://localhost:" + port);
......
......@@ -412,7 +412,7 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
contextCustomizer.accept(applicationContext);
Map<String, Object> properties = new HashMap<>();
properties.put("endpointPath", endpointPath);
properties.put("server.error.include-details", "always");
properties.put("server.error.include-message", "always");
applicationContext.getEnvironment().getPropertySources().addLast(new MapPropertySource("test", properties));
applicationContext.refresh();
try {
......
......@@ -46,9 +46,14 @@ public class ErrorProperties {
private IncludeStacktrace includeStacktrace = IncludeStacktrace.NEVER;
/**
* When to include "message" and "errors" attributes.
* When to include "message" attribute.
*/
private IncludeDetails includeDetails = IncludeDetails.NEVER;
private IncludeAttribute includeMessage = IncludeAttribute.NEVER;
/**
* When to include "errors" attribute.
*/
private IncludeAttribute includeBindingErrors = IncludeAttribute.NEVER;
private final Whitelabel whitelabel = new Whitelabel();
......@@ -76,12 +81,20 @@ public class ErrorProperties {
this.includeStacktrace = includeStacktrace;
}
public IncludeDetails getIncludeDetails() {
return this.includeDetails;
public IncludeAttribute getIncludeMessage() {
return this.includeMessage;
}
public void setIncludeMessage(IncludeAttribute includeMessage) {
this.includeMessage = includeMessage;
}
public void setIncludeDetails(IncludeDetails includeDetails) {
this.includeDetails = includeDetails;
public IncludeAttribute getIncludeBindingErrors() {
return this.includeMessage;
}
public void setIncludeBindingErrors(IncludeAttribute includeMessage) {
this.includeMessage = includeMessage;
}
public Whitelabel getWhitelabel() {
......@@ -96,39 +109,56 @@ public class ErrorProperties {
/**
* Never add stacktrace information.
*/
NEVER,
NEVER(IncludeAttribute.NEVER),
/**
* Always add stacktrace information.
*/
ALWAYS,
ALWAYS(IncludeAttribute.ALWAYS),
/**
* Add error attribute when the appropriate request parameter is "true".
*/
ON_PARAM(IncludeAttribute.ON_PARAM),
/**
* Add stacktrace information when the "trace" request parameter is "true".
* @deprecated since 2.3.0 in favor of {@link #ON_PARAM}
*/
ON_TRACE_PARAM
@Deprecated
ON_TRACE_PARAM(IncludeAttribute.ON_PARAM);
private final IncludeAttribute include;
IncludeStacktrace(IncludeAttribute include) {
this.include = include;
}
public IncludeAttribute getInclude() {
return this.include;
}
}
/**
* Include error details attributes options.
* Include error attributes options.
*/
public enum IncludeDetails {
public enum IncludeAttribute {
/**
* Never add error detail information.
* Never add error attribute.
*/
NEVER,
/**
* Always add error detail information.
* Always add error attribute.
*/
ALWAYS,
/**
* Add error details information when the "details" request parameter is "true".
* Add error attribute when the appropriate request parameter is "true".
*/
ON_DETAILS_PARAM
ON_PARAM
}
......
......@@ -134,24 +134,26 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept
* @param includeStackTrace whether to include the error stacktrace information
* @return the error attributes as a Map
* @deprecated since 2.3.0 in favor of
* {@link #getErrorAttributes(ServerRequest, boolean, boolean)}
* {@link #getErrorAttributes(ServerRequest, boolean, boolean, boolean)}
*/
@Deprecated
protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
return this.errorAttributes.getErrorAttributes(request, includeStackTrace, false);
return this.errorAttributes.getErrorAttributes(request, includeStackTrace, false, false);
}
/**
* Extract the error attributes from the current request, to be used to populate error
* views or JSON payloads.
* @param request the source request
* @param includeStackTrace whether to include the error stacktrace information
* @param includeDetails whether to include message and errors attributes
* @param includeStackTrace whether to include the stacktrace attribute
* @param includeMessage whether to include the message attribute
* @param includeBindingErrors whether to include the errors attribute
* @return the error attributes as a Map
*/
protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace,
boolean includeDetails) {
return this.errorAttributes.getErrorAttributes(request, includeStackTrace, includeDetails);
boolean includeMessage, boolean includeBindingErrors) {
return this.errorAttributes.getErrorAttributes(request, includeStackTrace, includeMessage,
includeBindingErrors);
}
/**
......@@ -173,13 +175,23 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept
}
/**
* Check whether the details attribute has been set on the given request.
* Check whether the message attribute has been set on the given request.
* @param request the source request
* @return {@code true} if the message attribute has been requested, {@code false}
* otherwise
*/
protected boolean isMessageEnabled(ServerRequest request) {
return getBooleanParameter(request, "message");
}
/**
* Check whether the errors attribute has been set on the given request.
* @param request the source request
* @return {@code true} if the error details have been requested, {@code false}
* @return {@code true} if the errors attribute has been requested, {@code false}
* otherwise
*/
protected boolean isDetailsEnabled(ServerRequest request) {
return getBooleanParameter(request, "details");
protected boolean isBindingErrorsEnabled(ServerRequest request) {
return getBooleanParameter(request, "errors");
}
private boolean getBooleanParameter(ServerRequest request, String parameterName) {
......
......@@ -114,8 +114,10 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
*/
protected Mono<ServerResponse> renderErrorView(ServerRequest request) {
boolean includeStackTrace = isIncludeStackTrace(request, MediaType.TEXT_HTML);
boolean includeDetails = isIncludeDetails(request, MediaType.TEXT_HTML);
Map<String, Object> error = getErrorAttributes(request, includeStackTrace, includeDetails);
boolean includeMessage = isIncludeMessage(request, MediaType.TEXT_HTML);
boolean includeBindingErrors = isIncludeBindingErrors(request, MediaType.TEXT_HTML);
Map<String, Object> error = getErrorAttributes(request, includeStackTrace, includeMessage,
includeBindingErrors);
int errorStatus = getHttpStatus(error);
ServerResponse.BodyBuilder responseBody = ServerResponse.status(errorStatus).contentType(TEXT_HTML_UTF8);
return Flux.just(getData(errorStatus).toArray(new String[] {}))
......@@ -143,8 +145,10 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
*/
protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
boolean includeStackTrace = isIncludeStackTrace(request, MediaType.ALL);
boolean includeDetails = isIncludeDetails(request, MediaType.ALL);
Map<String, Object> error = getErrorAttributes(request, includeStackTrace, includeDetails);
boolean includeMessage = isIncludeMessage(request, MediaType.ALL);
boolean includeBindingErrors = isIncludeBindingErrors(request, MediaType.ALL);
Map<String, Object> error = getErrorAttributes(request, includeStackTrace, includeMessage,
includeBindingErrors);
return ServerResponse.status(getHttpStatus(error)).contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(error));
}
......@@ -155,10 +159,12 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the stacktrace attribute should be included
*/
@SuppressWarnings("deprecation")
protected boolean isIncludeStackTrace(ServerRequest request, MediaType produces) {
switch (this.errorProperties.getIncludeStacktrace()) {
case ALWAYS:
return true;
case ON_PARAM:
case ON_TRACE_PARAM:
return isTraceEnabled(request);
default:
......@@ -167,17 +173,34 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
}
/**
* Determine if the message and errors attributes should be included.
* Determine if the message attribute should be included.
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the message and errors attributes should be included
* @return if the message attribute should be included
*/
protected boolean isIncludeDetails(ServerRequest request, MediaType produces) {
switch (this.errorProperties.getIncludeDetails()) {
protected boolean isIncludeMessage(ServerRequest request, MediaType produces) {
switch (this.errorProperties.getIncludeMessage()) {
case ALWAYS:
return true;
case ON_DETAILS_PARAM:
return isDetailsEnabled(request);
case ON_PARAM:
return isMessageEnabled(request);
default:
return false;
}
}
/**
* Determine if the errors attribute should be included.
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the errors attribute should be included
*/
protected boolean isIncludeBindingErrors(ServerRequest request, MediaType produces) {
switch (this.errorProperties.getIncludeBindingErrors()) {
case ALWAYS:
return true;
case ON_PARAM:
return isBindingErrorsEnabled(request);
default:
return false;
}
......
......@@ -74,25 +74,30 @@ public abstract class AbstractErrorController implements ErrorController {
* @param includeStackTrace if stack trace elements should be included
* @return the error attributes
* @deprecated since 2.3.0 in favor of
* {@link #getErrorAttributes(HttpServletRequest, boolean, boolean)}
* {@link #getErrorAttributes(HttpServletRequest, boolean, boolean, boolean)}
*/
@Deprecated
protected Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
return getErrorAttributes(request, includeStackTrace, false);
return getErrorAttributes(request, includeStackTrace, false, false);
}
protected Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace,
boolean includeDetails) {
boolean includeMessage, boolean includeBindingErrors) {
WebRequest webRequest = new ServletWebRequest(request);
return this.errorAttributes.getErrorAttributes(webRequest, includeStackTrace, includeDetails);
return this.errorAttributes.getErrorAttributes(webRequest, includeStackTrace, includeMessage,
includeBindingErrors);
}
protected boolean getTraceParameter(HttpServletRequest request) {
return getBooleanParameter(request, "trace");
}
protected boolean getDetailsParameter(HttpServletRequest request) {
return getBooleanParameter(request, "details");
protected boolean getMessageParameter(HttpServletRequest request) {
return getBooleanParameter(request, "message");
}
protected boolean getErrorsParameter(HttpServletRequest request) {
return getBooleanParameter(request, "errors");
}
protected boolean getBooleanParameter(HttpServletRequest request, String parameterName) {
......
......@@ -88,7 +88,8 @@ public class BasicErrorController extends AbstractErrorController {
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.TEXT_HTML), isIncludeDetails(request, MediaType.TEXT_HTML)));
isIncludeStackTrace(request, MediaType.TEXT_HTML), isIncludeMessage(request, MediaType.TEXT_HTML),
isIncludeBindingErrors(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
......@@ -101,7 +102,7 @@ public class BasicErrorController extends AbstractErrorController {
return new ResponseEntity<>(status);
}
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL),
isIncludeDetails(request, MediaType.ALL));
isIncludeMessage(request, MediaType.ALL), isIncludeBindingErrors(request, MediaType.TEXT_HTML));
return new ResponseEntity<>(body, status);
}
......@@ -117,10 +118,12 @@ public class BasicErrorController extends AbstractErrorController {
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the stacktrace attribute should be included
*/
@SuppressWarnings("deprecation")
protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
switch (getErrorProperties().getIncludeStacktrace()) {
case ALWAYS:
return true;
case ON_PARAM:
case ON_TRACE_PARAM:
return getTraceParameter(request);
default:
......@@ -129,17 +132,34 @@ public class BasicErrorController extends AbstractErrorController {
}
/**
* Determine if the error details attributes should be included.
* Determine if the message attribute should be included.
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the error details attributes should be included
* @return if the message attribute should be included
*/
protected boolean isIncludeDetails(HttpServletRequest request, MediaType produces) {
switch (getErrorProperties().getIncludeDetails()) {
protected boolean isIncludeMessage(HttpServletRequest request, MediaType produces) {
switch (getErrorProperties().getIncludeMessage()) {
case ALWAYS:
return true;
case ON_DETAILS_PARAM:
return getDetailsParameter(request);
case ON_PARAM:
return getMessageParameter(request);
default:
return false;
}
}
/**
* Determine if the errors attribute should be included.
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the errors attribute should be included
*/
protected boolean isIncludeBindingErrors(HttpServletRequest request, MediaType produces) {
switch (getErrorProperties().getIncludeMessage()) {
case ALWAYS:
return true;
case ON_PARAM:
return getErrorsParameter(request);
default:
return false;
}
......
......@@ -37,7 +37,11 @@
}
},
{
"name": "server.error.include-details",
"name": "server.error.include-binding-errors",
"defaultValue": "never"
},
{
"name": "server.error.include-message",
"defaultValue": "never"
},
{
......
......@@ -99,7 +99,7 @@ class DefaultErrorWebExceptionHandlerIntegrationTests {
@Test
void htmlError() {
this.contextRunner.withPropertyValues("server.error.include-details=always").run((context) -> {
this.contextRunner.withPropertyValues("server.error.include-message=always").run((context) -> {
WebTestClient client = getWebClient(context);
String body = client.get().uri("/").accept(MediaType.TEXT_HTML).exchange().expectStatus()
.isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR).expectHeader().contentType(TEXT_HTML_UTF8)
......@@ -116,24 +116,26 @@ class DefaultErrorWebExceptionHandlerIntegrationTests {
.isBadRequest().expectBody().jsonPath("status").isEqualTo("400").jsonPath("error")
.isEqualTo(HttpStatus.BAD_REQUEST.getReasonPhrase()).jsonPath("path").isEqualTo(("/bind"))
.jsonPath("exception").doesNotExist().jsonPath("errors").doesNotExist().jsonPath("message")
.isNotEmpty().jsonPath("requestId").isEqualTo(this.logIdFilter.getLogId());
.isEmpty().jsonPath("requestId").isEqualTo(this.logIdFilter.getLogId());
});
}
@Test
void bindingResultErrorIncludeDetails() {
this.contextRunner.withPropertyValues("server.error.include-details=on-details-param").run((context) -> {
WebTestClient client = getWebClient(context);
client.post().uri("/bind?details=true").contentType(MediaType.APPLICATION_JSON).bodyValue("{}").exchange()
.expectStatus().isBadRequest().expectBody().jsonPath("status").isEqualTo("400").jsonPath("error")
.isEqualTo(HttpStatus.BAD_REQUEST.getReasonPhrase()).jsonPath("path").isEqualTo(("/bind"))
.jsonPath("exception").doesNotExist().jsonPath("errors").isArray().jsonPath("message").isNotEmpty()
.jsonPath("requestId").isEqualTo(this.logIdFilter.getLogId());
});
void bindingResultErrorIncludeMessageAndErrors() {
this.contextRunner.withPropertyValues("server.error.include-message=on-param",
"server.error.include-binding-errors=on-param").run((context) -> {
WebTestClient client = getWebClient(context);
client.post().uri("/bind?message=true&errors=true").contentType(MediaType.APPLICATION_JSON)
.bodyValue("{}").exchange().expectStatus().isBadRequest().expectBody().jsonPath("status")
.isEqualTo("400").jsonPath("error").isEqualTo(HttpStatus.BAD_REQUEST.getReasonPhrase())
.jsonPath("path").isEqualTo(("/bind")).jsonPath("exception").doesNotExist()
.jsonPath("errors").isArray().jsonPath("message").isNotEmpty().jsonPath("requestId")
.isEqualTo(this.logIdFilter.getLogId());
});
}
@Test
void includeStackTraceOnParam() {
void includeStackTraceOnTraceParam() {
this.contextRunner.withPropertyValues("server.error.include-exception=true",
"server.error.include-stacktrace=on-trace-param").run((context) -> {
WebTestClient client = getWebClient(context);
......@@ -146,6 +148,21 @@ class DefaultErrorWebExceptionHandlerIntegrationTests {
});
}
@Test
void includeStackTraceOnParam() {
this.contextRunner
.withPropertyValues("server.error.include-exception=true", "server.error.include-stacktrace=on-param")
.run((context) -> {
WebTestClient client = getWebClient(context);
client.get().uri("/?trace=true").exchange().expectStatus()
.isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR).expectBody().jsonPath("status")
.isEqualTo("500").jsonPath("error")
.isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase()).jsonPath("exception")
.isEqualTo(IllegalStateException.class.getName()).jsonPath("trace").exists()
.jsonPath("requestId").isEqualTo(this.logIdFilter.getLogId());
});
}
@Test
void alwaysIncludeStackTrace() {
this.contextRunner
......@@ -177,11 +194,12 @@ class DefaultErrorWebExceptionHandlerIntegrationTests {
}
@Test
void includeDetailsOnParam() {
this.contextRunner.withPropertyValues("server.error.include-exception=true",
"server.error.include-details=on-details-param").run((context) -> {
void includeMessageOnParam() {
this.contextRunner
.withPropertyValues("server.error.include-exception=true", "server.error.include-message=on-param")
.run((context) -> {
WebTestClient client = getWebClient(context);
client.get().uri("/?details=true").exchange().expectStatus()
client.get().uri("/?message=true").exchange().expectStatus()
.isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR).expectBody().jsonPath("status")
.isEqualTo("500").jsonPath("error")
.isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase()).jsonPath("exception")
......@@ -191,9 +209,9 @@ class DefaultErrorWebExceptionHandlerIntegrationTests {
}
@Test
void alwaysIncludeDetails() {
void alwaysIncludeMessage() {
this.contextRunner
.withPropertyValues("server.error.include-exception=true", "server.error.include-details=always")
.withPropertyValues("server.error.include-exception=true", "server.error.include-message=always")
.run((context) -> {
WebTestClient client = getWebClient(context);
client.get().uri("/?trace=false").exchange().expectStatus()
......@@ -206,9 +224,9 @@ class DefaultErrorWebExceptionHandlerIntegrationTests {
}
@Test
void neverIncludeDetails() {
void neverIncludeMessage() {
this.contextRunner
.withPropertyValues("server.error.include-exception=true", "server.error.include-details=never")
.withPropertyValues("server.error.include-exception=true", "server.error.include-message=never")
.run((context) -> {
WebTestClient client = getWebClient(context);
client.get().uri("/?trace=true").exchange().expectStatus()
......@@ -235,7 +253,7 @@ class DefaultErrorWebExceptionHandlerIntegrationTests {
void defaultErrorView() {
this.contextRunner
.withPropertyValues("spring.mustache.prefix=classpath:/unknown/",
"server.error.include-stacktrace=always", "server.error.include-details=always")
"server.error.include-stacktrace=always", "server.error.include-message=always")
.run((context) -> {
WebTestClient client = getWebClient(context);
String body = client.get().uri("/").accept(MediaType.TEXT_HTML).exchange().expectStatus()
......@@ -250,7 +268,7 @@ class DefaultErrorWebExceptionHandlerIntegrationTests {
@Test
void escapeHtmlInDefaultErrorView() {
this.contextRunner
.withPropertyValues("spring.mustache.prefix=classpath:/unknown/", "server.error.include-details=always")
.withPropertyValues("spring.mustache.prefix=classpath:/unknown/", "server.error.include-message=always")
.run((context) -> {
WebTestClient client = getWebClient(context);
String body = client.get().uri("/html").accept(MediaType.TEXT_HTML).exchange().expectStatus()
......
......@@ -66,7 +66,8 @@ class DefaultErrorWebExceptionHandlerTests {
ResourceProperties resourceProperties = new ResourceProperties();
ErrorProperties errorProperties = new ErrorProperties();
ApplicationContext context = new AnnotationConfigReactiveWebApplicationContext();
given(errorAttributes.getErrorAttributes(any(), anyBoolean(), anyBoolean())).willReturn(getErrorAttributes());
given(errorAttributes.getErrorAttributes(any(), anyBoolean(), anyBoolean(), anyBoolean()))
.willReturn(getErrorAttributes());
DefaultErrorWebExceptionHandler exceptionHandler = new DefaultErrorWebExceptionHandler(errorAttributes,
resourceProperties, errorProperties, context);
setupViewResolver(exceptionHandler);
......
......@@ -69,7 +69,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @author Dave Syer
* @author Scott Frederick
*/
@SpringBootTest(properties = { "server.error.include-details=always" })
@SpringBootTest(properties = { "server.error.include-message=always" })
@DirtiesContext
class BasicErrorControllerMockMvcTests {
......
......@@ -52,7 +52,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @author Dave Syer
* @author Scott Frederick
*/
@SpringBootTest(properties = { "server.error.include-details=always" })
@SpringBootTest(properties = { "server.error.include-message=always" })
@DirtiesContext
class DefaultErrorViewIntegrationTests {
......
......@@ -51,7 +51,7 @@ class ErrorMvcAutoConfigurationTests {
ErrorAttributes errorAttributes = context.getBean(ErrorAttributes.class);
DispatcherServletWebRequest webRequest = createWebRequest(new IllegalStateException("Exception message"),
false);
errorView.render(errorAttributes.getErrorAttributes(webRequest, true, true), webRequest.getRequest(),
errorView.render(errorAttributes.getErrorAttributes(webRequest, true, true, true), webRequest.getRequest(),
webRequest.getResponse());
assertThat(webRequest.getResponse().getContentType()).isEqualTo("text/html;charset=UTF-8");
String responseString = ((MockHttpServletResponse) webRequest.getResponse()).getContentAsString();
......@@ -69,7 +69,7 @@ class ErrorMvcAutoConfigurationTests {
ErrorAttributes errorAttributes = context.getBean(ErrorAttributes.class);
DispatcherServletWebRequest webRequest = createWebRequest(new IllegalStateException("Exception message"),
true);
errorView.render(errorAttributes.getErrorAttributes(webRequest, true, true), webRequest.getRequest(),
errorView.render(errorAttributes.getErrorAttributes(webRequest, true, true, true), webRequest.getRequest(),
webRequest.getResponse());
assertThat(output).contains("Cannot render error page for request [/path] "
+ "and exception [Exception message] as the response has "
......
......@@ -71,7 +71,8 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro
properties.put("spring.resources.chain.cache", "false");
properties.put("spring.template.provider.cache", "false");
properties.put("spring.mvc.log-resolved-exception", "true");
properties.put("server.error.include-details", "ALWAYS");
properties.put("server.error.include-binding-errors", "ALWAYS");
properties.put("server.error.include-message", "ALWAYS");
properties.put("server.error.include-stacktrace", "ALWAYS");
properties.put("server.servlet.jsp.init-parameters.development", "true");
properties.put("spring.reactor.debug", "true");
......
......@@ -108,8 +108,8 @@ class DevToolPropertiesIntegrationTests {
ConfigurableEnvironment environment = this.context.getEnvironment();
String includeStackTrace = environment.getProperty("server.error.include-stacktrace");
assertThat(includeStackTrace).isEqualTo(ErrorProperties.IncludeStacktrace.ALWAYS.toString());
String includeDetails = environment.getProperty("server.error.include-details");
assertThat(includeDetails).isEqualTo(ErrorProperties.IncludeDetails.ALWAYS.toString());
String includeMessage = environment.getProperty("server.error.include-message");
assertThat(includeMessage).isEqualTo(ErrorProperties.IncludeAttribute.ALWAYS.toString());
}
protected ConfigurableApplicationContext getContext(Supplier<ConfigurableApplicationContext> supplier)
......
......@@ -30,7 +30,6 @@ import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
......@@ -82,12 +81,12 @@ public class DefaultErrorAttributes implements ErrorAttributes {
@Override
@Deprecated
public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
return getErrorAttributes(request, includeStackTrace, false);
return getErrorAttributes(request, includeStackTrace, false, false);
}
@Override
public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace,
boolean includeDetails) {
boolean includeMessage, boolean includeBindingErrors) {
Map<String, Object> errorAttributes = new LinkedHashMap<>();
errorAttributes.put("timestamp", new Date());
errorAttributes.put("path", request.path());
......@@ -97,9 +96,9 @@ public class DefaultErrorAttributes implements ErrorAttributes {
HttpStatus errorStatus = determineHttpStatus(error, responseStatusAnnotation);
errorAttributes.put("status", errorStatus.value());
errorAttributes.put("error", errorStatus.getReasonPhrase());
errorAttributes.put("message", determineMessage(error, responseStatusAnnotation, includeDetails));
errorAttributes.put("message", determineMessage(error, responseStatusAnnotation, includeMessage));
errorAttributes.put("requestId", request.exchange().getRequest().getId());
handleException(errorAttributes, determineException(error), includeStackTrace, includeDetails);
handleException(errorAttributes, determineException(error), includeStackTrace, includeBindingErrors);
return errorAttributes;
}
......@@ -111,13 +110,13 @@ public class DefaultErrorAttributes implements ErrorAttributes {
}
private String determineMessage(Throwable error, MergedAnnotation<ResponseStatus> responseStatusAnnotation,
boolean includeDetails) {
if (error instanceof WebExchangeBindException) {
return includeDetails ? error.getMessage() : "Validation failed";
}
if (!includeDetails) {
boolean includeMessage) {
if (!includeMessage) {
return "";
}
if (error instanceof BindingResult) {
return error.getMessage();
}
if (error instanceof ResponseStatusException) {
return ((ResponseStatusException) error).getReason();
}
......@@ -143,14 +142,14 @@ public class DefaultErrorAttributes implements ErrorAttributes {
}
private void handleException(Map<String, Object> errorAttributes, Throwable error, boolean includeStackTrace,
boolean includeDetails) {
boolean includeBindingErrors) {
if (this.includeException) {
errorAttributes.put("exception", error.getClass().getName());
}
if (includeStackTrace) {
addStackTrace(errorAttributes, error);
}
if (includeDetails && (error instanceof BindingResult)) {
if (includeBindingErrors && (error instanceof BindingResult)) {
BindingResult result = (BindingResult) error;
if (result.hasErrors()) {
errorAttributes.put("errors", result.getAllErrors());
......
......@@ -36,10 +36,10 @@ public interface ErrorAttributes {
* Return a {@link Map} of the error attributes. The map can be used as the model of
* an error page, or returned as a {@link ServerResponse} body.
* @param request the source request
* @param includeStackTrace if stack trace elements should be included
* @param includeStackTrace if stack trace attribute should be included
* @return a map of error attributes
* @deprecated since 2.3.0 in favor of
* {@link #getErrorAttributes(ServerRequest, boolean, boolean)}
* {@link #getErrorAttributes(ServerRequest, boolean, boolean, boolean)}
*/
Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace);
......@@ -47,11 +47,13 @@ public interface ErrorAttributes {
* Return a {@link Map} of the error attributes. The map can be used as the model of
* an error page, or returned as a {@link ServerResponse} body.
* @param request the source request
* @param includeStackTrace if stack trace elements should be included
* @param includeDetails if message and errors elements should be included
* @param includeStackTrace if stack trace attribute should be included
* @param includeMessage if message attribute should be included
* @param includeBindingErrors if errors attribute should be included
* @return a map of error attributes
*/
Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace, boolean includeDetails);
Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace, boolean includeMessage,
boolean includeBindingErrors);
/**
* Return the underlying cause of the error or {@code null} if the error cannot be
......
......@@ -104,16 +104,16 @@ public class DefaultErrorAttributes implements ErrorAttributes, HandlerException
@Override
@Deprecated
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
return getErrorAttributes(webRequest, includeStackTrace, false);
return getErrorAttributes(webRequest, includeStackTrace, false, false);
}
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace,
boolean includeDetails) {
boolean includeMessage, boolean includeBindingErrors) {
Map<String, Object> errorAttributes = new LinkedHashMap<>();
errorAttributes.put("timestamp", new Date());
addStatus(errorAttributes, webRequest);
addErrorDetails(errorAttributes, webRequest, includeStackTrace, includeDetails);
addErrorDetails(errorAttributes, webRequest, includeStackTrace, includeMessage, includeBindingErrors);
addPath(errorAttributes, webRequest);
return errorAttributes;
}
......@@ -136,7 +136,7 @@ public class DefaultErrorAttributes implements ErrorAttributes, HandlerException
}
private void addErrorDetails(Map<String, Object> errorAttributes, WebRequest webRequest, boolean includeStackTrace,
boolean includeDetails) {
boolean includeMessage, boolean includeBindingErrors) {
Throwable error = getError(webRequest);
if (error != null) {
while (error instanceof ServletException && error.getCause() != null) {
......@@ -149,24 +149,24 @@ public class DefaultErrorAttributes implements ErrorAttributes, HandlerException
addStackTrace(errorAttributes, error);
}
}
addErrorMessage(errorAttributes, webRequest, error, includeDetails);
addErrorMessage(errorAttributes, webRequest, error, includeMessage, includeBindingErrors);
}
private void addErrorMessage(Map<String, Object> errorAttributes, WebRequest webRequest, Throwable error,
boolean includeDetails) {
boolean includeMessage, boolean includeBindingErrors) {
BindingResult result = extractBindingResult(error);
if (result == null) {
addExceptionErrorMessage(errorAttributes, webRequest, error, includeDetails);
addExceptionErrorMessage(errorAttributes, webRequest, error, includeMessage);
}
else {
addBindingResultErrorMessage(errorAttributes, result, includeDetails);
addBindingResultErrorMessage(errorAttributes, result, includeMessage, includeBindingErrors);
}
}
private void addExceptionErrorMessage(Map<String, Object> errorAttributes, WebRequest webRequest, Throwable error,
boolean includeDetails) {
if (!includeDetails) {
errorAttributes.put("message", "An error occurred while processing the request");
boolean includeMessage) {
if (!includeMessage) {
errorAttributes.put("message", "");
return;
}
Object message = getAttribute(webRequest, RequestDispatcher.ERROR_MESSAGE);
......@@ -180,16 +180,12 @@ public class DefaultErrorAttributes implements ErrorAttributes, HandlerException
}
private void addBindingResultErrorMessage(Map<String, Object> errorAttributes, BindingResult result,
boolean includeDetails) {
if (!includeDetails) {
errorAttributes.put("message", "Validation failed");
return;
}
if (result.hasErrors()) {
boolean includeMessage, boolean includeBindingErrors) {
errorAttributes.put("message", (includeMessage) ? "Validation failed for object='" + result.getObjectName()
+ "'. " + "Error count: " + result.getErrorCount() : "");
if (includeBindingErrors && result.hasErrors()) {
errorAttributes.put("errors", result.getAllErrors());
}
errorAttributes.put("message", "Validation failed for object='" + result.getObjectName() + "'. "
+ "Error count: " + result.getErrorCount());
}
private BindingResult extractBindingResult(Throwable error) {
......
......@@ -37,10 +37,10 @@ public interface ErrorAttributes {
* an error page {@link ModelAndView}, or returned as a
* {@link ResponseBody @ResponseBody}.
* @param webRequest the source request
* @param includeStackTrace if stack trace elements should be included
* @param includeStackTrace if stack trace element should be included
* @return a map of error attributes
* @deprecated since 2.3.0 in favor of
* {@link #getErrorAttributes(WebRequest, boolean, boolean)}
* {@link #getErrorAttributes(WebRequest, boolean, boolean, boolean)}
*/
@Deprecated
Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace);
......@@ -50,12 +50,14 @@ public interface ErrorAttributes {
* an error page {@link ModelAndView}, or returned as a
* {@link ResponseBody @ResponseBody}.
* @param webRequest the source request
* @param includeStackTrace if stack trace elements should be included
* @param includeDetails if message and errors elements should be included
* @param includeStackTrace if stack trace element should be included
* @param includeMessage if message element should be included
* @param includeBindingErrors if errors element should be included
* @return a map of error attributes
* @since 2.3.0
*/
Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace, boolean includeDetails);
Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace, boolean includeMessage,
boolean includeBindingErrors);
/**
* Return the underlying cause of the error or {@code null} if the error cannot be
......
......@@ -54,21 +54,21 @@ class DefaultErrorAttributesTests {
@Test
void includeTimeStamp() {
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false, false);
assertThat(attributes.get("timestamp")).isInstanceOf(Date.class);
}
@Test
void specificStatusCode() {
this.request.setAttribute("javax.servlet.error.status_code", 404);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false, false);
assertThat(attributes.get("error")).isEqualTo(HttpStatus.NOT_FOUND.getReasonPhrase());
assertThat(attributes.get("status")).isEqualTo(404);
}
@Test
void missingStatusCode() {
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false, false);
assertThat(attributes.get("error")).isEqualTo("None");
assertThat(attributes.get("status")).isEqualTo(999);
}
......@@ -78,7 +78,7 @@ class DefaultErrorAttributesTests {
RuntimeException ex = new RuntimeException("Test");
ModelAndView modelAndView = this.errorAttributes.resolveException(this.request, null, null, ex);
this.request.setAttribute("javax.servlet.error.exception", new RuntimeException("Ignored"));
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true, false);
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(ex);
assertThat(modelAndView).isNull();
assertThat(attributes.containsKey("exception")).isFalse();
......@@ -86,46 +86,46 @@ class DefaultErrorAttributesTests {
}
@Test
void servletErrorWithDetail() {
void servletErrorWithMessage() {
RuntimeException ex = new RuntimeException("Test");
this.request.setAttribute("javax.servlet.error.exception", ex);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true, false);
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(ex);
assertThat(attributes.containsKey("exception")).isFalse();
assertThat(attributes.get("message")).isEqualTo("Test");
}
@Test
void servletErrorWithoutDetail() {
void servletErrorWithoutMessage() {
RuntimeException ex = new RuntimeException("Test");
this.request.setAttribute("javax.servlet.error.exception", ex);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false, false);
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(ex);
assertThat(attributes.containsKey("exception")).isFalse();
assertThat(attributes.get("message").toString()).contains("An error occurred");
assertThat(attributes.get("message").toString()).contains("");
}
@Test
void servletMessageWithDetail() {
void servletMessageWithMessage() {
this.request.setAttribute("javax.servlet.error.message", "Test");
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true, false);
assertThat(attributes.containsKey("exception")).isFalse();
assertThat(attributes.get("message")).isEqualTo("Test");
}
@Test
void servletMessageWithoutDetail() {
void servletMessageWithoutMessage() {
this.request.setAttribute("javax.servlet.error.message", "Test");
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false, false);
assertThat(attributes.containsKey("exception")).isFalse();
assertThat(attributes.get("message")).asString().contains("An error occurred");
assertThat(attributes.get("message")).asString().contains("");
}
@Test
void nullExceptionMessage() {
this.request.setAttribute("javax.servlet.error.exception", new RuntimeException());
this.request.setAttribute("javax.servlet.error.message", "Test");
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true, false);
assertThat(attributes.containsKey("exception")).isFalse();
assertThat(attributes.get("message")).isEqualTo("Test");
}
......@@ -133,7 +133,7 @@ class DefaultErrorAttributesTests {
@Test
void nullExceptionMessageAndServletMessage() {
this.request.setAttribute("javax.servlet.error.exception", new RuntimeException());
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true, false);
assertThat(attributes.containsKey("exception")).isFalse();
assertThat(attributes.get("message")).isEqualTo("No message available");
}
......@@ -143,7 +143,7 @@ class DefaultErrorAttributesTests {
RuntimeException ex = new RuntimeException("Test");
ServletException wrapped = new ServletException(new ServletException(ex));
this.request.setAttribute("javax.servlet.error.exception", wrapped);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true, false);
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(wrapped);
assertThat(attributes.containsKey("exception")).isFalse();
assertThat(attributes.get("message")).isEqualTo("Test");
......@@ -153,7 +153,7 @@ class DefaultErrorAttributesTests {
void getError() {
Error error = new OutOfMemoryError("Test error");
this.request.setAttribute("javax.servlet.error.exception", error);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, true, false);
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(error);
assertThat(attributes.containsKey("exception")).isFalse();
assertThat(attributes.get("message")).isEqualTo("Test error");
......@@ -183,17 +183,17 @@ class DefaultErrorAttributesTests {
testBindingResult(bindingResult, ex, true);
}
private void testBindingResult(BindingResult bindingResult, Exception ex, boolean includeDetails) {
private void testBindingResult(BindingResult bindingResult, Exception ex, boolean includeMessageAndErrors) {
this.request.setAttribute("javax.servlet.error.exception", ex);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false,
includeDetails);
if (includeDetails) {
includeMessageAndErrors, includeMessageAndErrors);
if (includeMessageAndErrors) {
assertThat(attributes.get("message"))
.isEqualTo("Validation failed for object='objectName'. Error count: 1");
assertThat(attributes.get("errors")).isEqualTo(bindingResult.getAllErrors());
}
else {
assertThat(attributes.get("message")).isEqualTo("Validation failed");
assertThat(attributes.get("message")).isEqualTo("");
assertThat(attributes.containsKey("errors")).isFalse();
}
}
......@@ -203,7 +203,7 @@ class DefaultErrorAttributesTests {
DefaultErrorAttributes errorAttributes = new DefaultErrorAttributes(true);
RuntimeException ex = new RuntimeException("Test");
this.request.setAttribute("javax.servlet.error.exception", ex);
Map<String, Object> attributes = errorAttributes.getErrorAttributes(this.webRequest, false, true);
Map<String, Object> attributes = errorAttributes.getErrorAttributes(this.webRequest, false, true, false);
assertThat(attributes.get("exception")).isEqualTo(RuntimeException.class.getName());
assertThat(attributes.get("message")).isEqualTo("Test");
}
......@@ -212,7 +212,7 @@ class DefaultErrorAttributesTests {
void withStackTraceAttribute() {
RuntimeException ex = new RuntimeException("Test");
this.request.setAttribute("javax.servlet.error.exception", ex);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, true, false);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, true, false, false);
assertThat(attributes.get("trace").toString()).startsWith("java.lang");
}
......@@ -220,14 +220,14 @@ class DefaultErrorAttributesTests {
void withoutStackTraceAttribute() {
RuntimeException ex = new RuntimeException("Test");
this.request.setAttribute("javax.servlet.error.exception", ex);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false, false);
assertThat(attributes.containsKey("trace")).isFalse();
}
@Test
void path() {
this.request.setAttribute("javax.servlet.error.request_uri", "path");
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false);
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest, false, false, false);
assertThat(attributes.get("path")).isEqualTo("path");
}
......
......@@ -37,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Scott Frederick
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = { "server.error.include-details=always" })
properties = { "server.error.include-message=always" })
class SampleActuatorCustomSecurityApplicationTests extends AbstractSampleActuatorCustomSecurityTests {
@LocalServerPort
......
......@@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Dave Syer
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "server.error.include-details=always" })
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "server.error.include-message=always" })
class SampleActuatorUiApplicationTests {
@Autowired
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment