Resolve absolute resource links in ResourceTransformers
Prior to this commit, `ResourceTransformer` implementations would
resolve internal links to other resources: both relative and absolute
request paths.
For relative request paths, those transformers would call
`ResourceTransformerSupport.resolveUrlPath` with the resource path,
as provided in the original file. This can cause problems when a
`CachingResourceResolver` is configured in the resolver chain, because
this resolver is caching resources, deriving the cache key from the
given resource path — this can cause collisions for cases like this:
resources/
|--foo/
| |--foo.css (imports style.css)
| |--style.css
|--bar/
| |--bar.css (imports style.css)
| |--style.css
The first "style.css" resolved resource is then cached and will be given
to any request asking for "style.css".
To avoid those issues, this commit improves the `ResourceTransformer`
implementations to calculate the absolute request path before asking the
chain to resolve the resource URL, thus avoiding duplications.
The resource chain will be then asked to resolve "/foo/style/css" or
"/bar/style.css".
Issue: SPR-14597
This commit is contained in:
@@ -146,7 +146,7 @@ public class AppCacheManifestTransformer extends ResourceTransformerSupport {
|
||||
Resource appCacheResource = transformerChain.getResolverChain()
|
||||
.resolveResource(null, info.getLine(), Collections.singletonList(resource));
|
||||
|
||||
String path = resolveUrlPath(info.getLine(), request, resource, transformerChain);
|
||||
String path = resolveUrlPath(toAbsolutePath(info.getLine(), request), request, resource, transformerChain);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Link modified: " + path + " (original: " + info.getLine() + ")");
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport {
|
||||
String link = content.substring(linkSegment.getStart(), linkSegment.getEnd());
|
||||
String newLink = null;
|
||||
if (!hasScheme(link)) {
|
||||
newLink = resolveUrlPath(link, request, resource, transformerChain);
|
||||
newLink = resolveUrlPath(toAbsolutePath(link, request), request, resource, transformerChain);
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (newLink != null && !link.equals(newLink)) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Collections;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A base class for a {@code ResourceTransformer} with an optional helper method
|
||||
@@ -86,6 +87,20 @@ public abstract class ResourceTransformerSupport implements ResourceTransformer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the given relative request path to an absolute path,
|
||||
* taking the path of the given request as a point of reference.
|
||||
* The resulting path is also cleaned from sequences like "path/..".
|
||||
* @param path the relative path to transform
|
||||
* @param request the referer request
|
||||
* @return the absolute request path for the given resource path
|
||||
*/
|
||||
protected String toAbsolutePath(String path, HttpServletRequest request) {
|
||||
String requestPath = this.getResourceUrlProvider().getUrlPathHelper().getRequestUri(request);
|
||||
String absolutePath = StringUtils.applyRelativePath(requestPath, path);
|
||||
return StringUtils.cleanPath(absolutePath);
|
||||
}
|
||||
|
||||
private ResourceUrlProvider findResourceUrlProvider(HttpServletRequest request) {
|
||||
if (this.resourceUrlProvider != null) {
|
||||
return this.resourceUrlProvider;
|
||||
|
||||
Reference in New Issue
Block a user