Preserve ETag HTTP header for versioned resources

Prior to this change, a resource handler chain configured with a
`VersionResourceResolver` would add the resource version to the request
attributes when serving that resource. This approach would not work when
a `CachingResourceResolver` is configured and the resource is already
cached. Indeed, that code path is not executed when the resource is
resolved from the cache.

This commit adds a new `VersionedResource` interface that's used by the
`VersionResourceResolver`, adding a `getVersion()` method that returns
the version string for that resource. This way, the version information
is cached with the resource itself and the request attributes are no
longer used for this.

Issue: SPR-13817
(cherry picked from commit 473cf9c)
This commit is contained in:
Brian Clozel
2016-01-05 14:55:14 +01:00
parent 84e5234eb5
commit 1581597092
5 changed files with 143 additions and 36 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -87,7 +87,6 @@ public class ResourceHttpRequestHandlerTests {
@Test
public void getResource() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");
this.request.setAttribute(VersionResourceResolver.RESOURCE_VERSION_ATTRIBUTE, "versionString");
this.handler.handleRequest(this.request, this.response);
assertEquals("text/css", this.response.getContentType());
@@ -95,7 +94,6 @@ public class ResourceHttpRequestHandlerTests {
assertEquals("max-age=3600", this.response.getHeader("Cache-Control"));
assertTrue(this.response.containsHeader("Last-Modified"));
assertEquals(this.response.getHeader("Last-Modified"), resourceLastModifiedDate("test/foo.css"));
assertEquals("\"versionString\"", this.response.getHeader("ETag"));
assertEquals("h1 { color:red; }", this.response.getContentAsString());
}
@@ -110,6 +108,19 @@ public class ResourceHttpRequestHandlerTests {
assertEquals(this.response.getHeader("Last-Modified"), resourceLastModifiedDate("test/foo.css"));
}
@Test
public void getVersionedResource() throws Exception {
VersionResourceResolver versionResolver = new VersionResourceResolver()
.addFixedVersionStrategy("versionString", "/**");
this.handler.setResourceResolvers(Arrays.asList(versionResolver, new PathResourceResolver()));
this.handler.afterPropertiesSet();
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "versionString/foo.css");
this.handler.handleRequest(this.request, this.response);
assertEquals("\"versionString\"", this.response.getHeader("ETag"));
}
@Test
@SuppressWarnings("deprecation")
public void getResourceHttp10BehaviorCache() throws Exception {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -28,6 +28,7 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.mock.web.test.MockHttpServletRequest;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
@@ -146,9 +147,10 @@ public class VersionResourceResolverTests {
this.resolver
.setStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.resolver.resolveResourceInternal(request, versionFile, this.locations, this.chain);
assertEquals(expected, actual);
assertEquals(expected.getFilename(), actual.getFilename());
verify(this.versionStrategy, times(1)).getResourceVersion(expected);
assertEquals(version, request.getAttribute(VersionResourceResolver.RESOURCE_VERSION_ATTRIBUTE));
assertThat(actual, instanceOf(VersionedResource.class));
assertEquals(version, ((VersionedResource)actual).getVersion());
}
@Test