private ResourceUrlProvider createUrlProvider(List<ResourceResolver> resolvers) { ResourceWebHandler handler = new ResourceWebHandler(); handler.setLocations(Collections.singletonList(new ClassPathResource("test/", getClass()))); handler.setResourceResolvers(resolvers); ResourceUrlProvider urlProvider = new ResourceUrlProvider(); urlProvider.registerHandlers(Collections.singletonMap("/static/**", handler)); return urlProvider; }
@Override public void onApplicationEvent(ContextRefreshedEvent event) { if (this.handlerMap.isEmpty()) { detectResourceHandlers(event.getApplicationContext()); } }
/** * A transformer can use this method when a resource being transformed * contains links to other resources. Such links need to be replaced with the * public facing link as determined by the resource resolver chain (e.g. the * public URL may have a version inserted). * @param resourcePath the path to a resource that needs to be re-written * @param exchange the current exchange * @param resource the resource being transformed * @param transformerChain the transformer chain * @return the resolved URL or an empty {@link Mono} */ protected Mono<String> resolveUrlPath(String resourcePath, ServerWebExchange exchange, Resource resource, ResourceTransformerChain transformerChain) { if (resourcePath.startsWith("/")) { // full resource path ResourceUrlProvider urlProvider = getResourceUrlProvider(); return (urlProvider != null ? urlProvider.getForUriString(resourcePath, exchange) : Mono.empty()); } else { // try resolving as relative path return transformerChain.getResolverChain() .resolveUrlPath(resourcePath, Collections.singletonList(resource)); } }
/** * Get the public resource URL for the given URI string. * <p>The URI string is expected to be a path and if it contains a query or * fragment those will be preserved in the resulting public resource URL. * @param uriString the URI string to transform * @param exchange the current exchange * @return the resolved public resource URL path, or empty if unresolved */ public final Mono<String> getForUriString(String uriString, ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); int queryIndex = getQueryIndex(uriString); String lookupPath = uriString.substring(0, queryIndex); String query = uriString.substring(queryIndex); PathContainer parsedLookupPath = PathContainer.parsePath(lookupPath); return resolveResourceUrl(exchange, parsedLookupPath).map(resolvedPath -> request.getPath().contextPath().value() + resolvedPath + query); }
@Test // SPR-12647 public void bestPatternMatch() { ResourceWebHandler otherHandler = new ResourceWebHandler(); otherHandler.setLocations(this.locations); VersionResourceResolver versionResolver = new VersionResourceResolver(); versionResolver.setStrategyMap(Collections.singletonMap("/**", new ContentVersionStrategy())); List<ResourceResolver> resolvers = new ArrayList<>(); resolvers.add(versionResolver); resolvers.add(new PathResourceResolver()); otherHandler.setResourceResolvers(resolvers); this.handlerMap.put("/resources/*.css", otherHandler); this.urlProvider.registerHandlers(this.handlerMap); String path = "/resources/foo.css"; String url = this.urlProvider.getForUriString(path, this.exchange).block(TIMEOUT); assertEquals("/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css", url); }
/** * A variation on {@link #getForLookupPath(String)} that accepts a full request * URL path and returns the full request URL path to expose for public use. * @param exchange the current exchange * @param requestUrl the request URL path to resolve * @return the resolved public URL path, or {@code null} if unresolved */ public final Mono<String> getForRequestUrl(ServerWebExchange exchange, String requestUrl) { if (logger.isTraceEnabled()) { logger.trace("Getting resource URL for request URL \"" + requestUrl + "\""); } int prefixIndex = getLookupPathIndex(exchange); int suffixIndex = getEndPathIndex(requestUrl); String prefix = requestUrl.substring(0, prefixIndex); String suffix = requestUrl.substring(suffixIndex); String lookupPath = requestUrl.substring(prefixIndex, suffixIndex); return getForLookupPath(lookupPath).map(resolvedPath -> prefix + resolvedPath + suffix); }
@Override public void onApplicationEvent(ContextRefreshedEvent event) { if (isAutodetect()) { this.handlerMap.clear(); detectResourceHandlers(event.getApplicationContext()); if (this.handlerMap.isEmpty() && logger.isDebugEnabled()) { logger.debug("No resource handling mappings found"); } if (!this.handlerMap.isEmpty()) { this.autodetect = false; } } }
@Bean public ResourceUrlProvider resourceUrlProvider() { return new ResourceUrlProvider(); }
@Test // SPR-12592 @SuppressWarnings("resource") public void initializeOnce() { AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); context.setServletContext(new MockServletContext()); context.register(HandlerMappingConfiguration.class); context.refresh(); assertThat(context.getBean(ResourceUrlProvider.class).getHandlerMap(), Matchers.hasKey(pattern("/resources/**"))); }
/** * A transformer can use this method when a resource being transformed * contains links to other resources. Such links need to be replaced with the * public facing link as determined by the resource resolver chain (e.g. the * public URL may have a version inserted). * @param resourcePath the path to a resource that needs to be re-written * @param exchange the current exchange * @param resource the resource being transformed * @param transformerChain the transformer chain * @return the resolved URL or null */ protected Mono<String> resolveUrlPath(String resourcePath, ServerWebExchange exchange, Resource resource, ResourceTransformerChain transformerChain) { if (resourcePath.startsWith("/")) { // full resource path ResourceUrlProvider urlProvider = getResourceUrlProvider(); return (urlProvider != null ? urlProvider.getForRequestUrl(exchange, resourcePath) : Mono.empty()); } else { // try resolving as relative path return transformerChain.getResolverChain() .resolveUrlPath(resourcePath, Collections.singletonList(resource)); } }
if (getPathMatcher().match(pattern, lookupPath)) { matchingPatterns.add(pattern); Comparator<String> patternComparator = getPathMatcher().getPatternComparator(lookupPath); Collections.sort(matchingPatterns, patternComparator); String pathWithinMapping = getPathMatcher().extractPathWithinPattern(pattern, lookupPath); String pathMapping = lookupPath.substring(0, lookupPath.indexOf(pathWithinMapping)); if (logger.isTraceEnabled()) {
@Bean public ResourceUrlProvider resourceUrlProvider() { return new ResourceUrlProvider(); } }
private ResourceUrlProvider createUrlProvider(List<ResourceResolver> resolvers) { ResourceWebHandler handler = new ResourceWebHandler(); handler.setLocations(Collections.singletonList(new ClassPathResource("test/", getClass()))); handler.setResourceResolvers(resolvers); ResourceUrlProvider urlProvider = new ResourceUrlProvider(); urlProvider.registerHandlers(Collections.singletonMap("/resources/**", handler)); return urlProvider; }
@Test // SPR-13374 public void getStaticResourceUrlRequestWithQueryOrHash() { String url = "/resources/foo.css?foo=bar&url=http://example.org"; String resolvedUrl = this.urlProvider.getForUriString(url, this.exchange).block(TIMEOUT); assertEquals(url, resolvedUrl); url = "/resources/foo.css#hash"; resolvedUrl = this.urlProvider.getForUriString(url, this.exchange).block(TIMEOUT); assertEquals(url, resolvedUrl); }
private ResourceUrlProvider createUrlProvider(List<ResourceResolver> resolvers) { ResourceWebHandler handler = new ResourceWebHandler(); handler.setLocations(Collections.singletonList(new ClassPathResource("test/", getClass()))); handler.setResourceResolvers(resolvers); ResourceUrlProvider urlProvider = new ResourceUrlProvider(); urlProvider.registerHandlers(Collections.singletonMap("/static/**", handler)); return urlProvider; }
@Test public void getStaticResourceUrl() { String expected = "/resources/foo.css"; String actual = this.urlProvider.getForUriString(expected, this.exchange).block(TIMEOUT); assertEquals(expected, actual); }
@Test public void getVersionedResourceUrl() { VersionResourceResolver versionResolver = new VersionResourceResolver(); versionResolver.setStrategyMap(Collections.singletonMap("/**", new ContentVersionStrategy())); List<ResourceResolver> resolvers = new ArrayList<>(); resolvers.add(versionResolver); resolvers.add(new PathResourceResolver()); this.handler.setResourceResolvers(resolvers); String path = "/resources/foo.css"; String url = this.urlProvider.getForUriString(path, this.exchange).block(TIMEOUT); assertEquals("/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css", url); }