Skip to content

Commit 51f6e78

Browse files
committed
Fall back on */* during content negotiation for errors
Prior to this commit, gh-31936 enabled content negotiation for `@ExceptionHandler` annotated methods in Spring MVC and WebFlux. In the case of WebFlux, HTTP clients sending invalid media types in the "Accept" request header would fail with a `NotAcceptableStatusException` This exception would be handled with an HTTP 406 response status, instead of processing the original exception. This commit ensures that invalid media types are ignored during the exception handling phase and that we fall back to "*/*". Fixes gh-32878
1 parent 94348d9 commit 51f6e78

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolver.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.springframework.web.reactive.result.method.InvocableHandlerMethod;
6161
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
6262
import org.springframework.web.reactive.result.method.SyncInvocableHandlerMethod;
63+
import org.springframework.web.server.NotAcceptableStatusException;
6364
import org.springframework.web.server.ServerWebExchange;
6465

6566
/**
@@ -416,7 +417,15 @@ private InvocableHandlerMethod createAttributeMethod(Object bean, Method method)
416417
public InvocableHandlerMethod getExceptionHandlerMethod(Throwable ex, ServerWebExchange exchange, @Nullable HandlerMethod handlerMethod) {
417418

418419
Class<?> handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null);
419-
List<MediaType> requestedMediaTypes = this.contentTypeResolver.resolveMediaTypes(exchange);
420+
List<MediaType> requestedMediaTypes = List.of(MediaType.ALL);
421+
try {
422+
requestedMediaTypes = this.contentTypeResolver.resolveMediaTypes(exchange);
423+
}
424+
catch (NotAcceptableStatusException exc) {
425+
if (logger.isDebugEnabled()) {
426+
logger.debug("Could not parse Accept header for requested media types", exc);
427+
}
428+
}
420429

421430
// Controller-local first
422431
if (handlerType != null) {

spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolverTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,18 @@ void exceptionHandlerWithMediaType() {
258258
assertThat(producibleMediaTypes).isNotEmpty().contains(MediaType.APPLICATION_JSON);
259259
}
260260

261+
@Test
262+
void exceptionHandlerWithInvalidAcceptHeader() {
263+
Method method = ResolvableMethod.on(ExceptionHandlerController.class).mockCall(ExceptionHandlerController::handle).method();
264+
this.handlerMethod = new HandlerMethod(new ExceptionHandlerController(), method);
265+
MockServerHttpRequest httpRequest = MockServerHttpRequest.get("/test").header("Accept", "v=12").build();
266+
MockServerWebExchange serverWebExchange = MockServerWebExchange.builder(httpRequest).build();
267+
InvocableHandlerMethod invocable = this.methodResolver.getExceptionHandlerMethod(
268+
new ResponseStatusException(HttpStatus.BAD_REQUEST, "reason"), serverWebExchange, this.handlerMethod);
269+
270+
assertThat(invocable).as("No match").isNotNull();
271+
}
272+
261273

262274
private static HandlerMethodArgumentResolver next(
263275
List<? extends HandlerMethodArgumentResolver> resolvers, AtomicInteger index) {

0 commit comments

Comments
 (0)