@Override protected Mono<Resource> resolveResourceInternal(@Nullable ServerWebExchange exchange, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveResource(exchange, requestPath, locations) .switchIfEmpty(Mono.defer(() -> { String webJarsResourcePath = findWebJarResourcePath(requestPath); if (webJarsResourcePath != null) { return chain.resolveResource(exchange, webJarsResourcePath, locations); } else { return Mono.empty(); } })); }
@Override protected Mono<String> resolveUrlPathInternal(String resourceUrlPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveUrlPath(resourceUrlPath, locations); }
@Override protected Mono<String> resolveUrlPathInternal(String resourceUrlPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveUrlPath(resourceUrlPath, locations) .flatMap(baseUrl -> { if (StringUtils.hasText(baseUrl)) { VersionStrategy strategy = getStrategyForPath(resourceUrlPath); if (strategy == null) { return Mono.just(baseUrl); } return chain.resolveResource(null, baseUrl, locations) .flatMap(resource -> strategy.getResourceVersion(resource) .map(version -> strategy.addVersion(baseUrl, version))); } return Mono.empty(); }); }
@Override protected Mono<String> resolveUrlPathInternal(String resourceUrlPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveUrlPath(resourceUrlPath, locations) .then(baseUrl -> { if (StringUtils.hasText(baseUrl)) { VersionStrategy versionStrategy = getStrategyForPath(resourceUrlPath); if (versionStrategy == null) { return Mono.empty(); } if (logger.isTraceEnabled()) { logger.trace("Getting the original resource to determine version " + "for path \"" + resourceUrlPath + "\""); } return chain.resolveResource(null, baseUrl, locations) .map(resource -> { String version = versionStrategy.getResourceVersion(resource); if (logger.isTraceEnabled()) { logger.trace("Determined version [" + version + "] for " + resource); } return versionStrategy.addVersion(baseUrl, version); }); } return Mono.empty(); }); }
@Override protected Mono<Resource> resolveResourceInternal(@Nullable ServerWebExchange exchange, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveResource(exchange, requestPath, locations) .map(resource -> { if (exchange == null || isGzipAccepted(exchange)) { try { Resource gzipped = new GzippedResource(resource); if (gzipped.exists()) { resource = gzipped; } } catch (IOException ex) { String logPrefix = exchange != null ? exchange.getLogPrefix() : ""; logger.trace(logPrefix + "No gzip resource for [" + resource.getFilename() + "]", ex); } } return resource; }); }
@Override protected Mono<String> resolveUrlPathInternal(String resourceUrlPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveUrlPath(resourceUrlPath, locations); }
@Override protected Mono<Resource> resolveResourceInternal(@Nullable ServerWebExchange exchange, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveResource(exchange, requestPath, locations) .switchIfEmpty(Mono.defer(() -> resolveVersionedResource(exchange, requestPath, locations, chain))); }
@Override protected Mono<String> resolveUrlPathInternal(String resourceUrlPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveUrlPath(resourceUrlPath, locations) .switchIfEmpty(Mono.defer(() -> { String webJarResourcePath = findWebJarResourcePath(resourceUrlPath); if (webJarResourcePath != null) { return chain.resolveUrlPath(webJarResourcePath, locations); } else { return Mono.empty(); } })); }
@Override protected Mono<Resource> resolveResourceInternal(@Nullable ServerWebExchange exchange, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) { String key = computeKey(exchange, requestPath); Resource cachedResource = this.cache.get(key, Resource.class); if (cachedResource != null) { String logPrefix = exchange != null ? exchange.getLogPrefix() : ""; logger.trace(logPrefix + "Resource resolved from cache"); return Mono.just(cachedResource); } return chain.resolveResource(exchange, requestPath, locations) .doOnNext(resource -> this.cache.put(key, resource)); }
@Override protected Mono<String> resolveUrlPathInternal(String resourceUrlPath, List<? extends Resource> locations, ResourceResolverChain chain) { String key = RESOLVED_URL_PATH_CACHE_KEY_PREFIX + resourceUrlPath; String cachedUrlPath = this.cache.get(key, String.class); if (cachedUrlPath != null) { logger.trace("Path resolved from cache"); return Mono.just(cachedUrlPath); } return chain.resolveUrlPath(resourceUrlPath, locations) .doOnNext(resolvedPath -> this.cache.put(key, resolvedPath)); }
protected Mono<Resource> getResource(ServerWebExchange exchange) { String name = HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE; PathContainer pathWithinHandler = exchange.getRequiredAttribute(name); String path = processPath(pathWithinHandler.value()); if (!StringUtils.hasText(path) || isInvalidPath(path)) { return Mono.empty(); } if (isInvalidEncodedPath(path)) { return Mono.empty(); } Assert.state(this.resolverChain != null, "ResourceResolverChain not initialized"); Assert.state(this.transformerChain != null, "ResourceTransformerChain not initialized"); return this.resolverChain.resolveResource(exchange, path, getLocations()) .flatMap(resource -> this.transformerChain.transform(exchange, resource)); }
/** * 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)); } }
@Override protected Mono<Resource> resolveResourceInternal(@Nullable ServerWebExchange exchange, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveResource(exchange, requestPath, locations).map(resource -> { if (exchange == null) { return resource; } String acceptEncoding = getAcceptEncoding(exchange); if (acceptEncoding == null) { return resource; } for (String coding : this.contentCodings) { if (acceptEncoding.contains(coding)) { try { String extension = getExtension(coding); Resource encoded = new EncodedResource(resource, coding, extension); if (encoded.exists()) { return encoded; } } catch (IOException ex) { logger.trace(exchange.getLogPrefix() + "No " + coding + " resource for [" + resource.getFilename() + "]", ex); } } } return resource; }); }
private Mono<String> resolveResourceUrl(ServerWebExchange exchange, PathContainer lookupPath) { return this.handlerMap.entrySet().stream() .filter(entry -> entry.getKey().matches(lookupPath)) .min((entry1, entry2) -> PathPattern.SPECIFICITY_COMPARATOR.compare(entry1.getKey(), entry2.getKey())) .map(entry -> { PathContainer path = entry.getKey().extractPathWithinPattern(lookupPath); int endIndex = lookupPath.elements().size() - path.elements().size(); PathContainer mapping = lookupPath.subPath(0, endIndex); ResourceWebHandler handler = entry.getValue(); List<ResourceResolver> resolvers = handler.getResourceResolvers(); ResourceResolverChain chain = new DefaultResourceResolverChain(resolvers); return chain.resolveUrlPath(path.value(), handler.getLocations()) .map(resolvedPath -> mapping.value() + resolvedPath); }) .orElseGet(() ->{ if (logger.isTraceEnabled()) { logger.trace(exchange.getLogPrefix() + "No match for \"" + lookupPath + "\""); } return Mono.empty(); }); }
private Mono<Resource> resolveVersionedResource(@Nullable ServerWebExchange exchange, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) { VersionStrategy versionStrategy = getStrategyForPath(requestPath); if (versionStrategy == null) { return Mono.empty(); } String candidate = versionStrategy.extractVersion(requestPath); if (StringUtils.isEmpty(candidate)) { return Mono.empty(); } String simplePath = versionStrategy.removeVersion(requestPath, candidate); return chain.resolveResource(exchange, simplePath, locations) .filterWhen(resource -> versionStrategy.getResourceVersion(resource) .map(actual -> { if (candidate.equals(actual)) { return true; } else { if (logger.isTraceEnabled()) { String logPrefix = exchange != null ? exchange.getLogPrefix() : ""; logger.trace(logPrefix + "Found resource for \"" + requestPath + "\", but version [" + candidate + "] does not match"); } return false; } })) .map(resource -> new FileNameVersionedResource(resource, candidate)); }
@Test public void resolverUrlPath() { String expected = "/foo.css"; String actual = this.chain.resolveUrlPath(expected, this.locations).block(TIMEOUT); assertEquals(expected, actual); }
@Test public void resolveResourceExisting() { Resource expected = mock(Resource.class); this.locations = singletonList(new ClassPathResource("/META-INF/resources/webjars/", getClass())); String file = "foo/2.3/foo.txt"; given(this.chain.resolveResource(this.exchange, file, this.locations)).willReturn(Mono.just(expected)); Resource actual = this.resolver .resolveResource(this.exchange, file, this.locations, this.chain) .block(TIMEOUT); assertEquals(expected, actual); verify(this.chain, times(1)).resolveResource(this.exchange, file, this.locations); }
@Test public void resolverUrlPathNoMatch() { assertNull(this.chain.resolveUrlPath("invalid.css", this.locations).block(TIMEOUT)); }
@Test public void resolveResourceNotFound() { String file = "something/something.js"; given(this.chain.resolveResource(this.exchange, file, this.locations)).willReturn(Mono.empty()); Resource actual = this.resolver .resolveResource(this.exchange, file, this.locations, this.chain) .block(TIMEOUT); assertNull(actual); verify(this.chain, times(1)).resolveResource(this.exchange, file, this.locations); verify(this.chain, never()).resolveResource(this.exchange, null, this.locations); }
@Test public void resolveUrlExistingNotInJarFile() { this.locations = singletonList(new ClassPathResource("/META-INF/resources/webjars/", getClass())); String file = "foo/foo.txt"; given(this.chain.resolveUrlPath(file, this.locations)).willReturn(Mono.empty()); String actual = this.resolver.resolveUrlPath(file, this.locations, this.chain).block(TIMEOUT); assertNull(actual); verify(this.chain, times(1)).resolveUrlPath(file, this.locations); verify(this.chain, never()).resolveUrlPath("foo/2.3/foo.txt", this.locations); }