diff --git a/framework-docs/modules/ROOT/pages/core/aot.adoc b/framework-docs/modules/ROOT/pages/core/aot.adoc index a07ea864dba8..33c3b20af066 100644 --- a/framework-docs/modules/ROOT/pages/core/aot.adoc +++ b/framework-docs/modules/ROOT/pages/core/aot.adoc @@ -167,7 +167,7 @@ Kotlin:: ---- ====== -WARNING: Kotlin class names with backticks using invalid Java identifiers (not starting by a letter, containing spaces, etc.) are not supported. +WARNING: Kotlin class names with backticks that use invalid Java identifiers (not starting with a letter, containing spaces, etc.) are not supported. Since there isn't any particular condition on this class, `dataSourceConfiguration` and `dataSource` are identified as candidates. The AOT engine will convert the configuration class above to code similar to the following: diff --git a/spring-web/src/main/java/org/springframework/web/accept/HeaderContentNegotiationStrategy.java b/spring-web/src/main/java/org/springframework/web/accept/HeaderContentNegotiationStrategy.java index 9ef86aabfd1a..32bf811d30ca 100644 --- a/spring-web/src/main/java/org/springframework/web/accept/HeaderContentNegotiationStrategy.java +++ b/spring-web/src/main/java/org/springframework/web/accept/HeaderContentNegotiationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2024 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. @@ -23,6 +23,7 @@ import org.springframework.http.InvalidMediaTypeException; import org.springframework.http.MediaType; import org.springframework.util.CollectionUtils; +import org.springframework.util.InvalidMimeTypeException; import org.springframework.util.MimeTypeUtils; import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.context.request.NativeWebRequest; @@ -55,7 +56,7 @@ public List resolveMediaTypes(NativeWebRequest request) MimeTypeUtils.sortBySpecificity(mediaTypes); return !CollectionUtils.isEmpty(mediaTypes) ? mediaTypes : MEDIA_TYPE_ALL_LIST; } - catch (InvalidMediaTypeException ex) { + catch (InvalidMediaTypeException | InvalidMimeTypeException ex) { throw new HttpMediaTypeNotAcceptableException( "Could not parse 'Accept' header " + headerValues + ": " + ex.getMessage()); } diff --git a/spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java b/spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java index b5115cf9662e..f952fb0b9efa 100644 --- a/spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java +++ b/spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java @@ -30,10 +30,11 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; /** - * Test fixture for HeaderContentNegotiationStrategy tests. + * Tests for {@link HeaderContentNegotiationStrategy}. * * @author Rossen Stoyanchev * @author Juergen Hoeller + * @author Sam Brannen */ class HeaderContentNegotiationStrategyTests { @@ -49,31 +50,48 @@ void resolveMediaTypes() throws Exception { this.servletRequest.addHeader("Accept", "text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"); List mediaTypes = this.strategy.resolveMediaTypes(this.webRequest); - assertThat(mediaTypes).hasSize(4); - assertThat(mediaTypes.get(0).toString()).isEqualTo("text/html"); - assertThat(mediaTypes.get(1).toString()).isEqualTo("text/x-c"); - assertThat(mediaTypes.get(2).toString()).isEqualTo("text/x-dvi;q=0.8"); - assertThat(mediaTypes.get(3).toString()).isEqualTo("text/plain;q=0.5"); + assertThat(mediaTypes).map(Object::toString) + .containsExactly("text/html", "text/x-c", "text/x-dvi;q=0.8", "text/plain;q=0.5"); } - @Test // SPR-14506 - public void resolveMediaTypesFromMultipleHeaderValues() throws Exception { + @Test // gh-19075 + void resolveMediaTypesFromMultipleHeaderValues() throws Exception { this.servletRequest.addHeader("Accept", "text/plain; q=0.5, text/html"); this.servletRequest.addHeader("Accept", "text/x-dvi; q=0.8, text/x-c"); List mediaTypes = this.strategy.resolveMediaTypes(this.webRequest); - assertThat(mediaTypes).hasSize(4); - assertThat(mediaTypes.get(0).toString()).isEqualTo("text/html"); - assertThat(mediaTypes.get(1).toString()).isEqualTo("text/x-c"); - assertThat(mediaTypes.get(2).toString()).isEqualTo("text/x-dvi;q=0.8"); - assertThat(mediaTypes.get(3).toString()).isEqualTo("text/plain;q=0.5"); + assertThat(mediaTypes).map(Object::toString) + .containsExactly("text/html", "text/x-c", "text/x-dvi;q=0.8", "text/plain;q=0.5"); + } + + @Test // gh-32483 + void resolveMediaTypesWithMaxElements() throws Exception { + String acceptHeaderValue = "text/plain, text/html,".repeat(25); + this.servletRequest.addHeader("Accept", acceptHeaderValue); + List mediaTypes = this.strategy.resolveMediaTypes(this.webRequest); + + assertThat(mediaTypes).hasSize(50); + assertThat(mediaTypes.stream().map(Object::toString).distinct()) + .containsExactly("text/plain", "text/html"); + } + + @Test // gh-32483 + void resolveMediaTypesWithTooManyElements() { + String acceptHeaderValue = "text/plain,".repeat(51); + this.servletRequest.addHeader("Accept", acceptHeaderValue); + assertThatExceptionOfType(HttpMediaTypeNotAcceptableException.class) + .isThrownBy(() -> this.strategy.resolveMediaTypes(this.webRequest)) + .withMessageStartingWith("Could not parse 'Accept' header") + .withMessageEndingWith("Too many elements"); } @Test void resolveMediaTypesParseError() { this.servletRequest.addHeader("Accept", "textplain; q=0.5"); - assertThatExceptionOfType(HttpMediaTypeNotAcceptableException.class).isThrownBy(() -> - this.strategy.resolveMediaTypes(this.webRequest)); + assertThatExceptionOfType(HttpMediaTypeNotAcceptableException.class) + .isThrownBy(() -> this.strategy.resolveMediaTypes(this.webRequest)) + .withMessageStartingWith("Could not parse 'Accept' header") + .withMessageContaining("Invalid mime type"); } }