001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.reactive.resource; 018 019import java.util.Collections; 020 021import reactor.core.publisher.Mono; 022 023import org.springframework.core.io.Resource; 024import org.springframework.lang.Nullable; 025import org.springframework.util.StringUtils; 026import org.springframework.web.server.ServerWebExchange; 027 028/** 029 * A base class for a {@code ResourceTransformer} with an optional helper method 030 * for resolving public links within a transformed resource. 031 * 032 * @author Rossen Stoyanchev 033 * @author Brian Clozel 034 * @since 5.0 035 */ 036public abstract class ResourceTransformerSupport implements ResourceTransformer { 037 038 @Nullable 039 private ResourceUrlProvider resourceUrlProvider; 040 041 042 /** 043 * Configure a {@link ResourceUrlProvider} to use when resolving the public 044 * URL of links in a transformed resource (e.g. import links in a CSS file). 045 * This is required only for links expressed as full paths and not for 046 * relative links. 047 * @param resourceUrlProvider the URL provider to use 048 */ 049 public void setResourceUrlProvider(@Nullable ResourceUrlProvider resourceUrlProvider) { 050 this.resourceUrlProvider = resourceUrlProvider; 051 } 052 053 /** 054 * Return the configured {@code ResourceUrlProvider}. 055 */ 056 @Nullable 057 public ResourceUrlProvider getResourceUrlProvider() { 058 return this.resourceUrlProvider; 059 } 060 061 062 /** 063 * A transformer can use this method when a resource being transformed 064 * contains links to other resources. Such links need to be replaced with the 065 * public facing link as determined by the resource resolver chain (e.g. the 066 * public URL may have a version inserted). 067 * @param resourcePath the path to a resource that needs to be re-written 068 * @param exchange the current exchange 069 * @param resource the resource being transformed 070 * @param transformerChain the transformer chain 071 * @return the resolved URL or an empty {@link Mono} 072 */ 073 protected Mono<String> resolveUrlPath(String resourcePath, ServerWebExchange exchange, 074 Resource resource, ResourceTransformerChain transformerChain) { 075 076 if (resourcePath.startsWith("/")) { 077 // full resource path 078 ResourceUrlProvider urlProvider = getResourceUrlProvider(); 079 return (urlProvider != null ? urlProvider.getForUriString(resourcePath, exchange) : Mono.empty()); 080 } 081 else { 082 // try resolving as relative path 083 return transformerChain.getResolverChain() 084 .resolveUrlPath(resourcePath, Collections.singletonList(resource)); 085 } 086 } 087 088 /** 089 * Transform the given relative request path to an absolute path, 090 * taking the path of the given request as a point of reference. 091 * The resulting path is also cleaned from sequences like "path/..". 092 * 093 * @param path the relative path to transform 094 * @param exchange the current exchange 095 * @return the absolute request path for the given resource path 096 */ 097 protected String toAbsolutePath(String path, ServerWebExchange exchange) { 098 String requestPath = exchange.getRequest().getURI().getPath(); 099 String absolutePath = (path.startsWith("/") ? path : StringUtils.applyRelativePath(requestPath, path)); 100 return StringUtils.cleanPath(absolutePath); 101 } 102 103}