parent
c5d6cc4134
commit
57e0c789a8
|
|
@ -29,15 +29,19 @@ import org.springframework.core.io.Resource;
|
|||
* A {@code ResourceResolver} that delegates to the chain to locate a resource
|
||||
* and then attempts to find a matching versioned resource contained in a WebJar JAR file.
|
||||
*
|
||||
* <p>This allows WabJar users to use version-less paths in their templates, like {@code "/jquery/jquery.min.js"}
|
||||
* while this path is resolved to the unique version {@code "/jquery/1.2.0/jquery.min.js"}, which is a better fit
|
||||
* for HTTP caching and version management in applications.
|
||||
* <p>This allows WebJars.org users to write version agnostic paths in their templates,
|
||||
* like {@code <script src="/jquery/jquery.min.js"/>}.
|
||||
* This path will be resolved to the unique version {@code <script src="/jquery/1.2.0/jquery.min.js"/>},
|
||||
* which is a better fit for HTTP caching and version management in applications.
|
||||
*
|
||||
* <p>This also resolves Resources for version agnostic HTTP requests {@code "GET /jquery/jquery.min.js"}.
|
||||
*
|
||||
* <p>This resolver requires the "org.webjars:webjars-locator" library on classpath, and is automatically
|
||||
* registered if that library is present.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 4.2
|
||||
* @see org.springframework.web.servlet.config.annotation.ResourceChainRegistration
|
||||
* @see <a href="http://www.webjars.org">webjars.org</a>
|
||||
*/
|
||||
public class WebJarsResourceResolver extends AbstractResourceResolver {
|
||||
|
|
@ -56,7 +60,12 @@ public class WebJarsResourceResolver extends AbstractResourceResolver {
|
|||
protected Resource resolveResourceInternal(HttpServletRequest request, String requestPath,
|
||||
List<? extends Resource> locations, ResourceResolverChain chain) {
|
||||
|
||||
return chain.resolveResource(request, requestPath, locations);
|
||||
Resource resolved = chain.resolveResource(request, requestPath, locations);
|
||||
if (resolved == null) {
|
||||
String webJarResourcePath = findWebJarResourcePath(requestPath);
|
||||
return chain.resolveResource(request, webJarResourcePath, locations);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -65,26 +74,31 @@ public class WebJarsResourceResolver extends AbstractResourceResolver {
|
|||
|
||||
String path = chain.resolveUrlPath(resourceUrlPath, locations);
|
||||
if (path == null) {
|
||||
try {
|
||||
int startOffset = resourceUrlPath.startsWith("/") ? 1 : 0;
|
||||
int endOffset = resourceUrlPath.indexOf("/", 1);
|
||||
if (endOffset != -1) {
|
||||
String webjar = resourceUrlPath.substring(startOffset, endOffset);
|
||||
String partialPath = resourceUrlPath.substring(endOffset);
|
||||
String webJarPath = webJarAssetLocator.getFullPath(webjar, partialPath);
|
||||
return chain.resolveUrlPath(webJarPath.substring(WEBJARS_LOCATION_LENGTH), locations);
|
||||
}
|
||||
}
|
||||
catch (MultipleMatchesException ex) {
|
||||
logger.warn("WebJar version conflict for \"" + resourceUrlPath + "\"", ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No WebJar resource found for \"" + resourceUrlPath + "\"");
|
||||
}
|
||||
}
|
||||
String webJarResourcePath = findWebJarResourcePath(resourceUrlPath);
|
||||
return chain.resolveUrlPath(webJarResourcePath, locations);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
protected String findWebJarResourcePath(String path) {
|
||||
try {
|
||||
int startOffset = path.startsWith("/") ? 1 : 0;
|
||||
int endOffset = path.indexOf("/", 1);
|
||||
if (endOffset != -1) {
|
||||
String webjar = path.substring(startOffset, endOffset);
|
||||
String partialPath = path.substring(endOffset);
|
||||
String webJarPath = webJarAssetLocator.getFullPath(webjar, partialPath);
|
||||
return webJarPath.substring(WEBJARS_LOCATION_LENGTH);
|
||||
}
|
||||
} catch (MultipleMatchesException ex) {
|
||||
logger.warn("WebJar version conflict for \"" + path + "\"", ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No WebJar resource found for \"" + path + "\"");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,11 +26,14 @@ import static org.mockito.Mockito.verify;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
|
||||
/**
|
||||
* Unit tests for
|
||||
|
|
@ -46,6 +49,8 @@ public class WebJarsResourceResolverTests {
|
|||
|
||||
private ResourceResolverChain chain;
|
||||
|
||||
private HttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// for this to work, an actual WebJar must be on the test classpath
|
||||
|
|
@ -104,4 +109,31 @@ public class WebJarsResourceResolverTests {
|
|||
verify(this.chain, times(1)).resolveUrlPath(file, this.locations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveResourceExisting() {
|
||||
Resource expected = mock(Resource.class);
|
||||
this.locations = Collections.singletonList(new ClassPathResource("/META-INF/resources/webjars/", getClass()));
|
||||
String file = "/foo/2.3/foo.txt";
|
||||
given(this.chain.resolveResource(this.request, file, this.locations)).willReturn(expected);
|
||||
|
||||
Resource actual = this.resolver.resolveResource(this.request, file, this.locations, this.chain);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
verify(this.chain, times(1)).resolveResource(this.request, file, this.locations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveResourceWebJar() {
|
||||
Resource expected = mock(Resource.class);
|
||||
String file = "/underscorejs/underscore.js";
|
||||
String expectedPath = "/underscorejs/1.8.2/underscore.js";
|
||||
this.locations = Collections.singletonList(new ClassPathResource("/META-INF/resources/webjars/", getClass()));
|
||||
given(this.chain.resolveResource(this.request, expectedPath, this.locations)).willReturn(expected);
|
||||
|
||||
Resource actual = this.resolver.resolveResource(this.request, file, this.locations, this.chain);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
verify(this.chain, times(1)).resolveResource(this.request, file, this.locations);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue