CachingResourceResolver varies by known codings only

Issue: SPR-16381
This commit is contained in:
Rossen Stoyanchev
2018-06-04 23:30:35 -04:00
parent 010352163b
commit 3acb96efd0
6 changed files with 157 additions and 33 deletions

View File

@@ -16,7 +16,9 @@
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.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
@@ -47,6 +49,8 @@ public class CachingResourceResolver extends AbstractResourceResolver {
private final Cache cache;
private final List<String> contentCodings = new ArrayList<>(EncodedResourceResolver.DEFAULT_CODINGS);
public CachingResourceResolver(Cache cache) {
Assert.notNull(cache, "Cache is required");
@@ -69,6 +73,33 @@ public class CachingResourceResolver extends AbstractResourceResolver {
return this.cache;
}
/**
* Configure the supported content codings from the
* {@literal "Accept-Encoding"} header for which to cache resource variations.
*
* <p>The codings configured here are generally expected to match those
* configured on {@link EncodedResourceResolver#setContentCodings(List)}.
*
* <p>By default this property is set to {@literal ["br", "gzip"]} based on
* the value of {@link EncodedResourceResolver#DEFAULT_CODINGS}.
*
* @param codings one or more supported content codings
* @since 5.1
*/
public void setContentCodings(List<String> codings) {
Assert.notEmpty(codings, "At least one content coding expected.");
this.contentCodings.clear();
this.contentCodings.addAll(codings);
}
/**
* Return a read-only list with the supported content codings.
* @since 5.1
*/
public List<String> getContentCodings() {
return Collections.unmodifiableList(this.contentCodings);
}
@Override
protected Resource resolveResourceInternal(@Nullable HttpServletRequest request, String requestPath,
@@ -100,7 +131,7 @@ public class CachingResourceResolver extends AbstractResourceResolver {
key.append(requestPath);
if (request != null) {
String codingKey = getContentCodingKey(request);
if (codingKey != null) {
if (StringUtils.hasText(codingKey)) {
key.append("+encoding=").append(codingKey);
}
}
@@ -108,7 +139,7 @@ public class CachingResourceResolver extends AbstractResourceResolver {
}
@Nullable
private static String getContentCodingKey(HttpServletRequest request) {
private String getContentCodingKey(HttpServletRequest request) {
String header = request.getHeader(HttpHeaders.ACCEPT_ENCODING);
if (!StringUtils.hasText(header)) {
return null;
@@ -118,8 +149,7 @@ public class CachingResourceResolver extends AbstractResourceResolver {
int index = token.indexOf(';');
return (index >= 0 ? token.substring(0, index) : token).trim().toLowerCase();
})
.filter(coding -> !coding.equals("*"))
.filter(coding -> !coding.equals("identity"))
.filter(this.contentCodings::contains)
.sorted()
.collect(Collectors.joining(","));
}

View File

@@ -53,7 +53,10 @@ import org.springframework.util.Assert;
*/
public class EncodedResourceResolver extends AbstractResourceResolver {
private final List<String> contentCodings = new ArrayList<>(Arrays.asList("br", "gzip"));
public static final List<String> DEFAULT_CODINGS = Arrays.asList("br", "gzip");
private final List<String> contentCodings = new ArrayList<>(DEFAULT_CODINGS);
private final Map<String, String> extensions = new LinkedHashMap<>();
@@ -71,11 +74,15 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
* is used.
*
* <p><strong>Note:</strong> Each coding must be associated with a file
* extension via {@link #registerExtension} or {@link #setExtensions}.
* extension via {@link #registerExtension} or {@link #setExtensions}. Also
* customizations to the list of codings here should be matched by
* customizations to the same list in {@link CachingResourceResolver} to
* ensure encoded variants of a resource are cached under separate keys.
*
* <p>By default this property is set to {@literal ["br", "gzip"]}.
*
* @param codings one or more supported content codings
* @since 5.1
*/
public void setContentCodings(List<String> codings) {
Assert.notEmpty(codings, "At least one content coding expected.");
@@ -85,6 +92,7 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
/**
* Return a read-only list with the supported content codings.
* @since 5.1
*/
public List<String> getContentCodings() {
return Collections.unmodifiableList(this.contentCodings);
@@ -97,6 +105,7 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
* {@literal ["gzip" -> ".gz"]}.
* @param extensions the extensions to use.
* @see #registerExtension(String, String)
* @since 5.1
*/
public void setExtensions(Map<String, String> extensions) {
extensions.forEach(this::registerExtension);
@@ -106,6 +115,7 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
* Java config friendly alternative to {@link #setExtensions(Map)}.
* @param coding the content coding
* @param extension the associated file extension
* @since 5.1
*/
public void registerExtension(String coding, String extension) {
this.extensions.put(coding, extension.startsWith(".") ? extension : "." + extension);
@@ -113,6 +123,7 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
/**
* Return a read-only map with coding-to-extension mappings.
* @since 5.1
*/
public Map<String, String> getExtensions() {
return Collections.unmodifiableMap(this.extensions);