diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/CachingResourceResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/CachingResourceResolver.java index 9c05bbde8ad..b7d205bc55c 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/CachingResourceResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/CachingResourceResolver.java @@ -17,10 +17,8 @@ package org.springframework.web.reactive.resource; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Locale; import java.util.stream.Collectors; import org.jspecify.annotations.Nullable; @@ -133,15 +131,12 @@ public class CachingResourceResolver extends AbstractResourceResolver { } private @Nullable String getContentCodingKey(ServerWebExchange exchange) { - String header = exchange.getRequest().getHeaders().getFirst("Accept-Encoding"); - if (!StringUtils.hasText(header)) { + List acceptedCodings = EncodedResourceResolver.parseAcceptEncoding(exchange); + if (acceptedCodings.isEmpty()) { return null; } - return Arrays.stream(StringUtils.tokenizeToStringArray(header, ",")) - .map(token -> { - int index = token.indexOf(';'); - return (index >= 0 ? token.substring(0, index) : token).trim().toLowerCase(Locale.ROOT); - }) + return acceptedCodings + .stream() .filter(this.contentCodings::contains) .sorted() .collect(Collectors.joining(",")); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java index 07c9345695b..000af7a8e8e 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java @@ -38,8 +38,8 @@ import reactor.core.publisher.Mono; import org.springframework.core.io.AbstractResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; -import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; /** @@ -142,23 +142,23 @@ public class EncodedResourceResolver extends AbstractResourceResolver { return resource; } - String acceptEncoding = getAcceptEncoding(exchange); - if (acceptEncoding == null) { + List acceptedCodings = parseAcceptEncoding(exchange); + if (acceptedCodings.isEmpty()) { return resource; } - for (String coding : this.contentCodings) { - if (acceptEncoding.contains(coding)) { + for (String acceptedCoding : acceptedCodings) { + if (this.contentCodings.contains(acceptedCoding)) { try { - String extension = getExtension(coding); - Resource encoded = new EncodedResource(resource, coding, extension); + String extension = getExtension(acceptedCoding); + Resource encoded = new EncodedResource(resource, acceptedCoding, extension); if (encoded.exists()) { return encoded; } } catch (IOException ex) { logger.trace(exchange.getLogPrefix() + - "No " + coding + " resource for [" + resource.getFilename() + "]", ex); + "No " + acceptedCoding + " resource for [" + resource.getFilename() + "]", ex); } } } @@ -167,12 +167,6 @@ public class EncodedResourceResolver extends AbstractResourceResolver { }); } - private @Nullable String getAcceptEncoding(ServerWebExchange exchange) { - ServerHttpRequest request = exchange.getRequest(); - String header = request.getHeaders().getFirst(HttpHeaders.ACCEPT_ENCODING); - return (header != null ? header.toLowerCase(Locale.ROOT) : null); - } - private String getExtension(String coding) { String extension = this.extensions.get(coding); if (extension == null) { @@ -188,6 +182,23 @@ public class EncodedResourceResolver extends AbstractResourceResolver { return chain.resolveUrlPath(resourceUrlPath, locations); } + /** + * Parse the accepted encodings from the given HTTP exchange request. + */ + static List parseAcceptEncoding(ServerWebExchange exchange) { + String header = exchange.getRequest().getHeaders().getFirst("Accept-Encoding"); + if (!StringUtils.hasText(header)) { + return Collections.emptyList(); + } + header = header.toLowerCase(Locale.ROOT); + return Arrays.stream(StringUtils.tokenizeToStringArray(header, ",")) + .map(token -> { + int index = token.indexOf(';'); + return (index >= 0 ? token.substring(0, index) : token).trim(); + }) + .toList(); + } + /** * An encoded {@link HttpResource}. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CachingResourceResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CachingResourceResolver.java index 17fd1df9465..f8575376d76 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CachingResourceResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CachingResourceResolver.java @@ -17,10 +17,8 @@ package org.springframework.web.servlet.resource; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Locale; import java.util.stream.Collectors; import jakarta.servlet.http.HttpServletRequest; @@ -29,7 +27,6 @@ import org.jspecify.annotations.Nullable; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.core.io.Resource; -import org.springframework.http.HttpHeaders; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -139,15 +136,12 @@ public class CachingResourceResolver extends AbstractResourceResolver { } private @Nullable String getContentCodingKey(HttpServletRequest request) { - String header = request.getHeader(HttpHeaders.ACCEPT_ENCODING); - if (!StringUtils.hasText(header)) { + List acceptedCodings = EncodedResourceResolver.parseAcceptEncoding(request); + if (acceptedCodings.isEmpty()) { return null; } - return Arrays.stream(StringUtils.tokenizeToStringArray(header, ",")) - .map(token -> { - int index = token.indexOf(';'); - return (index >= 0 ? token.substring(0, index) : token).trim().toLowerCase(Locale.ROOT); - }) + return acceptedCodings + .stream() .filter(this.contentCodings::contains) .sorted() .collect(Collectors.joining(",")); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java index 0b80b3b40d8..b42abc226c1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java @@ -39,6 +39,7 @@ import org.springframework.core.io.AbstractResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Resolver that delegates to the chain, and if a resource is found, it then @@ -139,23 +140,23 @@ public class EncodedResourceResolver extends AbstractResourceResolver { return resource; } - String acceptEncoding = getAcceptEncoding(request); - if (acceptEncoding == null) { + List acceptedCodings = parseAcceptEncoding(request); + if (acceptedCodings.isEmpty()) { return resource; } - for (String coding : this.contentCodings) { - if (acceptEncoding.contains(coding)) { + for (String acceptedCoding : acceptedCodings) { + if (this.contentCodings.contains(acceptedCoding)) { try { - String extension = getExtension(coding); - Resource encoded = new EncodedResource(resource, coding, extension); + String extension = getExtension(acceptedCoding); + Resource encoded = new EncodedResource(resource, acceptedCoding, extension); if (encoded.exists()) { return encoded; } } catch (IOException ex) { if (logger.isTraceEnabled()) { - logger.trace("No " + coding + " resource for [" + resource.getFilename() + "]", ex); + logger.trace("No " + acceptedCoding + " resource for [" + resource.getFilename() + "]", ex); } } } @@ -164,11 +165,6 @@ public class EncodedResourceResolver extends AbstractResourceResolver { return resource; } - private @Nullable String getAcceptEncoding(HttpServletRequest request) { - String header = request.getHeader(HttpHeaders.ACCEPT_ENCODING); - return (header != null ? header.toLowerCase(Locale.ROOT) : null); - } - private String getExtension(String coding) { String extension = this.extensions.get(coding); if (extension == null) { @@ -184,6 +180,23 @@ public class EncodedResourceResolver extends AbstractResourceResolver { return chain.resolveUrlPath(resourceUrlPath, locations); } + /** + * Parse the accepted encodings from the given HTTP request. + */ + static List parseAcceptEncoding(HttpServletRequest request) { + String header = request.getHeader("Accept-Encoding"); + if (!StringUtils.hasText(header)) { + return Collections.emptyList(); + } + header = header.toLowerCase(Locale.ROOT); + return Arrays.stream(StringUtils.tokenizeToStringArray(header, ",")) + .map(token -> { + int index = token.indexOf(';'); + return (index >= 0 ? token.substring(0, index) : token).trim(); + }) + .toList(); + } + /** * An encoded {@link HttpResource}.