Skip to content

Commit

Permalink
Call getErrorAttributes() only once
Browse files Browse the repository at this point in the history
Refine the fix introduced in commit 60b7e6c so that the
`getErrorAttributes()` method is not called multiple times. If the
status is missing, the `DefaultErrorWebExceptionHandler` will now
call an internal `DefaultErrorAttributes` instance in order to obtain
the actual status result.

Fixes gh-41732
  • Loading branch information
philwebb committed Aug 22, 2024
1 parent d974686 commit 05b73ce
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.springframework.boot.autoconfigure.web.WebProperties.Resources;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.error.ErrorAttributeOptions.Include;
import org.springframework.boot.web.reactive.error.DefaultErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -94,6 +95,8 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa

private static final ErrorAttributeOptions ONLY_STATUS = ErrorAttributeOptions.of(Include.STATUS);

private static final DefaultErrorAttributes defaultErrorAttributes = new DefaultErrorAttributes();

private final ErrorProperties errorProperties;

/**
Expand Down Expand Up @@ -121,8 +124,8 @@ protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes erro
* @return a {@code Publisher} of the HTTP response
*/
protected Mono<ServerResponse> renderErrorView(ServerRequest request) {
int status = getHttpStatus(getErrorAttributes(request, ONLY_STATUS));
Map<String, Object> errorAttributes = getErrorAttributes(request, MediaType.TEXT_HTML);
int status = getHttpStatus(request, errorAttributes);
ServerResponse.BodyBuilder responseBody = ServerResponse.status(status).contentType(TEXT_HTML_UTF8);
return Flux.just(getData(status).toArray(new String[] {}))
.flatMap((viewName) -> renderErrorView(viewName, responseBody, errorAttributes))
Expand All @@ -148,8 +151,8 @@ private List<String> getData(int errorStatus) {
* @return a {@code Publisher} of the HTTP response
*/
protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
int status = getHttpStatus(getErrorAttributes(request, ONLY_STATUS));
Map<String, Object> errorAttributes = getErrorAttributes(request, MediaType.ALL);
int status = getHttpStatus(request, errorAttributes);
return ServerResponse.status(status)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorAttributes));
Expand Down Expand Up @@ -234,6 +237,11 @@ protected boolean isIncludePath(ServerRequest request, MediaType produces) {
};
}

private int getHttpStatus(ServerRequest request, Map<String, Object> errorAttributes) {
return getHttpStatus(errorAttributes.containsKey("status") ? errorAttributes
: defaultErrorAttributes.getErrorAttributes(request, ONLY_STATUS));
}

/**
* Get the HTTP error status information from the error map.
* @param errorAttributes the current error information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import jakarta.validation.Valid;
Expand Down Expand Up @@ -597,6 +598,21 @@ void customErrorWebExceptionHandlerWithoutStatus() {
});
}

@Test
void customErrorAttributesWithoutStatus() {
this.contextRunner.withUserConfiguration(CustomErrorAttributesWithoutStatus.class).run((context) -> {
WebTestClient client = getWebClient(context);
client.get()
.uri("/badRequest")
.exchange()
.expectStatus()
.isBadRequest()
.expectBody()
.jsonPath("status")
.doesNotExist();
});
}

private String getErrorTemplatesLocation() {
String packageName = getClass().getPackage().getName();
return "classpath:/" + packageName.replace('.', '/') + "/templates/";
Expand Down Expand Up @@ -686,6 +702,7 @@ static class CustomErrorAttributesWithoutDelegation {
@Bean
ErrorAttributes errorAttributes() {
return new DefaultErrorAttributes() {

@Override
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
Map<String, Object> errorAttributes = new HashMap<>();
Expand Down Expand Up @@ -724,4 +741,23 @@ protected ErrorAttributeOptions getErrorAttributeOptions(ServerRequest request,

}

@Configuration(proxyBeanMethods = false)
static class CustomErrorAttributesWithoutStatus {

@Bean
ErrorAttributes errorAttributes() {
return new DefaultErrorAttributes() {

@Override
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
Map<String, Object> attributes = new LinkedHashMap<>(super.getErrorAttributes(request, options));
attributes.remove("status");
return attributes;
}

};
}

}

}

0 comments on commit 05b73ce

Please sign in to comment.