From 3090a3a71f6bdee4418a0b25d9812bdc9ee53b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Ramon?= Date: Tue, 23 Mar 2021 23:50:37 -0300 Subject: [PATCH 1/2] Ignore quality value when removing MediaType.ALL Update the default reactive exception handler so that `MediaType.ALL` is removed regardless of any quality setting. Prior to this commit, the "match-all" media type was not properly ignored if it has a quality value and would show HTML content if the accept header was `application/json, */*;q=0.9`. See gh-25778 --- .../DefaultErrorWebExceptionHandler.java | 2 +- .../DefaultErrorWebExceptionHandlerTests.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java index ea6cd7edf91..cc5fb2f7df1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java @@ -237,7 +237,7 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa return (serverRequest) -> { try { List acceptedMediaTypes = serverRequest.headers().accept(); - acceptedMediaTypes.remove(MediaType.ALL); + acceptedMediaTypes.removeIf((mediaType) -> MediaType.ALL.equalsTypeAndSubtype(mediaType)); MediaType.sortBySpecificityAndQuality(acceptedMediaTypes); return acceptedMediaTypes.stream().anyMatch(MediaType.TEXT_HTML::isCompatibleWith); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerTests.java index 3ad649c1848..e52a29e9199 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.web.reactive.error; import java.util.Collections; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; @@ -28,9 +29,12 @@ import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWeb import org.springframework.boot.web.reactive.error.ErrorAttributes; import org.springframework.context.ApplicationContext; import org.springframework.http.MediaType; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.ServerCodecConfigurer; 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.function.server.ServerRequest; import org.springframework.web.reactive.result.view.View; import org.springframework.web.reactive.result.view.ViewResolver; import org.springframework.web.server.ServerWebExchange; @@ -86,4 +90,21 @@ class DefaultErrorWebExceptionHandlerTests { exceptionHandler.setViewResolvers(Collections.singletonList(viewResolver)); } + @Test + void acceptsTextHtmlShouldNotConsiderMediaAllEvenWithQuality() { + ErrorAttributes errorAttributes = mock(ErrorAttributes.class); + ResourceProperties resourceProperties = new ResourceProperties(); + ErrorProperties errorProperties = new ErrorProperties(); + ApplicationContext context = new AnnotationConfigReactiveWebApplicationContext(); + DefaultErrorWebExceptionHandler exceptionHandler = new DefaultErrorWebExceptionHandler(errorAttributes, + resourceProperties, errorProperties, context); + MediaType allWithQuality = new MediaType(MediaType.ALL.getType(), MediaType.ALL.getSubtype(), 0.9); + MockServerWebExchange exchange = MockServerWebExchange + .from(MockServerHttpRequest.get("/test").accept(allWithQuality)); + List> readers = ServerCodecConfigurer.create().getReaders(); + ServerRequest request = ServerRequest.create(exchange, readers); + boolean accepts = exceptionHandler.acceptsTextHtml().test(request); + assertThat(accepts).isFalse(); + } + } From 88b74097baafd3d0c2ffec1a9c8e3c8509e5bfd1 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 24 Mar 2021 12:31:23 -0700 Subject: [PATCH 2/2] Polish 'Ignore quality value when removing MediaType.ALL' See gh-25778 --- .../reactive/error/DefaultErrorWebExceptionHandler.java | 4 ++-- .../error/DefaultErrorWebExceptionHandlerTests.java | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java index cc5fb2f7df1..604b1c5a699 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -237,7 +237,7 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa return (serverRequest) -> { try { List acceptedMediaTypes = serverRequest.headers().accept(); - acceptedMediaTypes.removeIf((mediaType) -> MediaType.ALL.equalsTypeAndSubtype(mediaType)); + acceptedMediaTypes.removeIf(MediaType.ALL::equalsTypeAndSubtype); MediaType.sortBySpecificityAndQuality(acceptedMediaTypes); return acceptedMediaTypes.stream().anyMatch(MediaType.TEXT_HTML::isCompatibleWith); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerTests.java index e52a29e9199..ba7ff5dfeef 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/error/DefaultErrorWebExceptionHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; /** - * Tests for {@link AbstractErrorWebExceptionHandler}. + * Tests for {@link DefaultErrorWebExceptionHandler}. * * @author Phillip Webb * @author Madhura Bhave @@ -66,10 +66,10 @@ class DefaultErrorWebExceptionHandlerTests { @Test void nonStandardErrorStatusCodeShouldNotFail() { ErrorAttributes errorAttributes = mock(ErrorAttributes.class); + given(errorAttributes.getErrorAttributes(any(), any())).willReturn(getErrorAttributes()); ResourceProperties resourceProperties = new ResourceProperties(); ErrorProperties errorProperties = new ErrorProperties(); ApplicationContext context = new AnnotationConfigReactiveWebApplicationContext(); - given(errorAttributes.getErrorAttributes(any(), any())).willReturn(getErrorAttributes()); DefaultErrorWebExceptionHandler exceptionHandler = new DefaultErrorWebExceptionHandler(errorAttributes, resourceProperties, errorProperties, context); setupViewResolver(exceptionHandler); @@ -103,8 +103,7 @@ class DefaultErrorWebExceptionHandlerTests { .from(MockServerHttpRequest.get("/test").accept(allWithQuality)); List> readers = ServerCodecConfigurer.create().getReaders(); ServerRequest request = ServerRequest.create(exchange, readers); - boolean accepts = exceptionHandler.acceptsTextHtml().test(request); - assertThat(accepts).isFalse(); + assertThat(exceptionHandler.acceptsTextHtml().test(request)).isFalse(); } }