Commit 4b4dc28a authored by Madhura Bhave's avatar Madhura Bhave

Support non-standard error codes with AbstractErrorWebExceptionHandler

Fixes gh-16691
parent a695e062
......@@ -62,6 +62,7 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept
* Currently duplicated from Spring WebFlux HttpWebHandlerAdapter.
*/
private static final Set<String> DISCONNECTED_CLIENT_EXCEPTIONS;
static {
Set<String> exceptions = new HashSet<>();
exceptions.add("AbortedException");
......@@ -276,7 +277,8 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept
if (logger.isDebugEnabled()) {
logger.debug(request.exchange().getLogPrefix() + formatError(throwable, request));
}
if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
if (HttpStatus.resolve(response.rawStatusCode()) != null
&& response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
logger.error(request.exchange().getLogPrefix() + "500 Server Error for " + formatRequest(request),
throwable);
}
......
......@@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.web.reactive.error;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
......@@ -113,16 +114,26 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
protected Mono<ServerResponse> renderErrorView(ServerRequest request) {
boolean includeStackTrace = isIncludeStackTrace(request, MediaType.TEXT_HTML);
Map<String, Object> error = getErrorAttributes(request, includeStackTrace);
HttpStatus errorStatus = getHttpStatus(error);
int errorStatus = getHttpStatus(error);
ServerResponse.BodyBuilder responseBody = ServerResponse.status(errorStatus).contentType(TEXT_HTML_UTF8);
return Flux
.just("error/" + errorStatus.value(), "error/" + SERIES_VIEWS.get(errorStatus.series()), "error/error")
return Flux.just(getData(errorStatus).toArray(new String[] {}))
.flatMap((viewName) -> renderErrorView(viewName, responseBody, error))
.switchIfEmpty(this.errorProperties.getWhitelabel().isEnabled()
? renderDefaultErrorView(responseBody, error) : Mono.error(getError(request)))
.next();
}
private List<String> getData(int errorStatus) {
HttpStatus errorHttpStatus = HttpStatus.resolve(errorStatus);
List<String> data = new ArrayList<>();
data.add("error/" + errorStatus);
if (errorHttpStatus != null) {
data.add("error/" + SERIES_VIEWS.get(errorHttpStatus.series()));
}
data.add("error/error");
return data;
}
/**
* Render the error information as a JSON payload.
* @param request the current request
......@@ -157,9 +168,8 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
* @param errorAttributes the current error information
* @return the error HTTP status
*/
protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
int statusCode = (int) errorAttributes.get("status");
return HttpStatus.valueOf(statusCode);
protected int getHttpStatus(Map<String, Object> errorAttributes) {
return (int) errorAttributes.get("status");
}
/**
......
......@@ -16,17 +16,37 @@
package org.springframework.boot.autoconfigure.web.reactive.error;
import java.util.Collections;
import java.util.Map;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.reactive.result.view.View;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.HttpWebHandlerAdapter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link AbstractErrorWebExceptionHandler}.
*
* @author Phillip Webb
* @author Madhura Bhave
*/
class DefaultErrorWebExceptionHandlerTests {
......@@ -39,4 +59,31 @@ class DefaultErrorWebExceptionHandlerTests {
assertThat(errorHandlers).isNotNull().isEqualTo(webHandlers);
}
@Test
void nonStandardErrorStatusCodeShouldNotFail() {
ErrorAttributes errorAttributes = mock(ErrorAttributes.class);
ResourceProperties resourceProperties = new ResourceProperties();
ErrorProperties errorProperties = new ErrorProperties();
ApplicationContext context = new AnnotationConfigReactiveWebApplicationContext();
given(errorAttributes.getErrorAttributes(any(), anyBoolean())).willReturn(getErrorAttributes());
DefaultErrorWebExceptionHandler exceptionHandler = new DefaultErrorWebExceptionHandler(errorAttributes,
resourceProperties, errorProperties, context);
setupViewResolver(exceptionHandler);
ServerWebExchange exchange = MockServerWebExchange
.from(MockServerHttpRequest.get("/some-other-path").accept(MediaType.TEXT_HTML));
exceptionHandler.handle(exchange, new RuntimeException()).block();
}
private Map<String, Object> getErrorAttributes() {
return Collections.singletonMap("status", 498);
}
private void setupViewResolver(DefaultErrorWebExceptionHandler exceptionHandler) {
View view = mock(View.class);
given(view.render(any(), any(), any())).willReturn(Mono.empty());
ViewResolver viewResolver = mock(ViewResolver.class);
given(viewResolver.resolveViewName(any(), any())).willReturn(Mono.just(view));
exceptionHandler.setViewResolvers(Collections.singletonList(viewResolver));
}
}
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