Improve support for caching encoded resources

The key in CachingResourceResolver now includes the "Accept-Encoding"
request header cleaned to exclude "*", "identity", and parameters, and
also sorted alphabetically.

For encoded resources the response now includes a response header with
"Vary: Accept-Encoding".

Issue: SPR-16381
This commit is contained in:
Rossen Stoyanchev
2018-05-23 09:10:07 -04:00
parent 9274de390a
commit b472d192f4
10 changed files with 91 additions and 28 deletions

View File

@@ -73,7 +73,7 @@ public class CachingResourceResolverTests {
@Test
public void resolveResourceInternalFromCache() {
Resource expected = Mockito.mock(Resource.class);
this.cache.put(CachingResourceResolver.RESOLVED_RESOURCE_CACHE_KEY_PREFIX + "bar.css", expected);
this.cache.put(getCacheKey("bar.css"), expected);
Resource actual = this.chain.resolveResource(null, "bar.css", this.locations);
assertSame(expected, actual);
@@ -110,10 +110,10 @@ public class CachingResourceResolverTests {
public void resolveResourceAcceptEncodingInCacheKey() {
String file = "bar.css";
MockHttpServletRequest request = new MockHttpServletRequest("GET", file);
request.addHeader("Accept-Encoding", "gzip");
request.addHeader("Accept-Encoding", "gzip ; a=b , deflate , brotli ; c=d ");
Resource expected = this.chain.resolveResource(request, file, this.locations);
String cacheKey = CachingResourceResolver.RESOLVED_RESOURCE_CACHE_KEY_PREFIX + file + "+encoding=gzip";
String cacheKey = getCacheKey(file + "+encoding=brotli,deflate,gzip");
Object actual = this.cache.get(cacheKey).get();
assertSame(expected, actual);
@@ -125,7 +125,7 @@ public class CachingResourceResolverTests {
MockHttpServletRequest request = new MockHttpServletRequest("GET", file);
Resource expected = this.chain.resolveResource(request, file, this.locations);
String cacheKey = CachingResourceResolver.RESOLVED_RESOURCE_CACHE_KEY_PREFIX + file;
String cacheKey = getCacheKey(file);
Object actual = this.cache.get(cacheKey).get();
assertEquals(expected, actual);
@@ -135,8 +135,8 @@ public class CachingResourceResolverTests {
public void resolveResourceMatchingEncoding() {
Resource resource = Mockito.mock(Resource.class);
Resource gzipped = Mockito.mock(Resource.class);
this.cache.put(CachingResourceResolver.RESOLVED_RESOURCE_CACHE_KEY_PREFIX + "bar.css", resource);
this.cache.put(CachingResourceResolver.RESOLVED_RESOURCE_CACHE_KEY_PREFIX + "bar.css+encoding=gzip", gzipped);
this.cache.put(getCacheKey("bar.css"), resource);
this.cache.put(getCacheKey("bar.css+encoding=gzip"), gzipped);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "bar.css");
assertSame(resource, this.chain.resolveResource(request,"bar.css", this.locations));
@@ -146,4 +146,8 @@ public class CachingResourceResolverTests {
assertSame(gzipped, this.chain.resolveResource(request, "bar.css", this.locations));
}
private static String getCacheKey(String key) {
return CachingResourceResolver.RESOLVED_RESOURCE_CACHE_KEY_PREFIX + key;
}
}

View File

@@ -36,6 +36,7 @@ import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.util.FileCopyUtils;
@@ -105,7 +106,11 @@ public class EncodedResourceResolverTests {
assertEquals(getResource(file + ".gz").getDescription(), actual.getDescription());
assertEquals(getResource(file).getFilename(), actual.getFilename());
assertTrue(actual instanceof HttpResource);
HttpHeaders headers = ((HttpResource) actual).getResponseHeaders();
assertEquals("gzip", headers.getFirst(HttpHeaders.CONTENT_ENCODING));
assertEquals("Accept-Encoding", headers.getFirst(HttpHeaders.VARY));
}
@Test