Removing remaining use of PathPattern with String path

This commit is contained in:
Rossen Stoyanchev
2017-07-07 19:11:13 +02:00
parent 00f4c36d7a
commit 9640cedeae
11 changed files with 90 additions and 79 deletions

View File

@@ -26,6 +26,7 @@ import reactor.core.publisher.Mono;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.server.reactive.PathContainer;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.pattern.PathPattern;
@@ -54,19 +55,18 @@ class PathResourceLookupFunction implements Function<ServerRequest, Mono<Resourc
@Override
public Mono<Resource> apply(ServerRequest request) {
String path = processPath(request.path());
PathContainer pathContainer = request.pathContainer();
if (!this.pattern.matches(pathContainer)) {
return Mono.empty();
}
pathContainer = this.pattern.extractPathWithinPattern(pathContainer);
String path = processPath(pathContainer.value());
if (path.contains("%")) {
path = StringUtils.uriDecode(path, StandardCharsets.UTF_8);
}
if (!StringUtils.hasLength(path) || isInvalidPath(path)) {
return Mono.empty();
}
if (!this.pattern.matches(path)) {
return Mono.empty();
}
else {
path = this.pattern.extractPathWithinPattern(path);
}
try {
Resource resource = this.location.createRelative(path);
if (resource.exists() && resource.isReadable() && isResourceUnderLocation(resource)) {

View File

@@ -341,10 +341,11 @@ public abstract class RequestPredicates {
@Override
public boolean test(ServerRequest request) {
boolean match = this.pattern.matches(request.pathContainer());
PathContainer pathContainer = request.pathContainer();
boolean match = this.pattern.matches(pathContainer);
traceMatch("Pattern", this.pattern.getPatternString(), request.path(), match);
if (match) {
mergeTemplateVariables(request, this.pattern.matchAndExtract(request.path()).getUriVariables());
mergeTemplateVariables(request, this.pattern.matchAndExtract(pathContainer).getUriVariables());
return true;
}
else {

View File

@@ -109,7 +109,7 @@ public class PathPatternRegistry<T> {
* patterns first, according to the given {@code lookupPath}.
* @param lookupPath the URL lookup path to be matched against
*/
public SortedSet<PathMatchResult<T>> findMatches(String lookupPath) {
public SortedSet<PathMatchResult<T>> findMatches(PathContainer lookupPath) {
return this.patternsMap.entrySet().stream()
.filter(entry -> entry.getKey().matches(lookupPath))
.sorted(Comparator.comparing(Map.Entry::getKey))

View File

@@ -16,6 +16,7 @@
package org.springframework.web.reactive.resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -30,6 +31,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.http.server.reactive.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.handler.PathMatchResult;
@@ -136,8 +138,9 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
}
/**
* 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.
* A variation on {@link #getForLookupPath(PathContainer)} 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 empty if unresolved
@@ -146,22 +149,16 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
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);
}
private int getLookupPathIndex(ServerWebExchange exchange) {
ServerHttpRequest request = exchange.getRequest();
String requestPath = request.getURI().getPath();
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
return requestPath.indexOf(lookupPath);
int queryIndex = getQueryIndex(requestUrl);
String lookupPath = requestUrl.substring(0, queryIndex);
String query = requestUrl.substring(queryIndex);
PathContainer parsedLookupPath = PathContainer.parse(lookupPath, StandardCharsets.UTF_8);
return getForLookupPath(parsedLookupPath).map(resolvedPath ->
request.getPath().contextPath().value() + resolvedPath + query);
}
private int getEndPathIndex(String lookupPath) {
private int getQueryIndex(String lookupPath) {
int suffixIndex = lookupPath.length();
int queryIndex = lookupPath.indexOf("?");
if (queryIndex > 0) {
@@ -186,35 +183,33 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
* @param lookupPath the lookup path to check
* @return the resolved public URL path, or empty if unresolved
*/
public final Mono<String> getForLookupPath(String lookupPath) {
public final Mono<String> getForLookupPath(PathContainer lookupPath) {
if (logger.isTraceEnabled()) {
logger.trace("Getting resource URL for lookup path \"" + lookupPath + "\"");
}
Set<PathMatchResult<ResourceWebHandler>> matchResults = this.patternRegistry.findMatches(lookupPath);
Set<PathMatchResult<ResourceWebHandler>> matches = this.patternRegistry.findMatches(lookupPath);
if (matchResults.isEmpty()) {
return Mono.empty();
}
return Flux.fromIterable(matchResults)
.concatMap(result -> {
String pathWithinMapping = result.getPattern().extractPathWithinPattern(lookupPath);
String pathMapping = lookupPath.substring(0, lookupPath.indexOf(pathWithinMapping));
return Flux.fromIterable(matches).next()
.flatMap(result -> {
PathContainer path = result.getPattern().extractPathWithinPattern(lookupPath);
int endIndex = lookupPath.elements().size() - path.elements().size();
PathContainer mapping = PathContainer.subPath(lookupPath, 0, endIndex);
if (logger.isTraceEnabled()) {
logger.trace("Invoking ResourceResolverChain for URL pattern \"" + result.getPattern() + "\"");
logger.trace("Invoking ResourceResolverChain for URL pattern " +
"\"" + result.getPattern() + "\"");
}
ResourceWebHandler handler = result.getHandler();
ResourceResolverChain chain = new DefaultResourceResolverChain(handler.getResourceResolvers());
return chain.resolveUrlPath(pathWithinMapping, handler.getLocations())
List<ResourceResolver> resolvers = handler.getResourceResolvers();
ResourceResolverChain chain = new DefaultResourceResolverChain(resolvers);
return chain.resolveUrlPath(path.value(), handler.getLocations())
.map(resolvedPath -> {
if (logger.isTraceEnabled()) {
logger.trace("Resolved public resource URL path \"" + resolvedPath + "\"");
}
return pathMapping + resolvedPath;
return mapping.value() + resolvedPath;
});
})
.next();
});
}
}

View File

@@ -16,6 +16,7 @@
package org.springframework.web.reactive.handler;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -28,6 +29,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.http.server.reactive.PathContainer;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
import org.springframework.web.util.pattern.PatternParseException;
@@ -73,14 +75,17 @@ public class PathPatternRegistryTests {
this.registry.register("/fo?", new Object());
this.registry.register("/f?o", new Object());
Set<PathMatchResult<Object>> matches = this.registry.findMatches("/foo");
PathContainer path = PathContainer.parse("/foo", StandardCharsets.UTF_8);
Set<PathMatchResult<Object>> matches = this.registry.findMatches(path);
assertThat(toPatterns(matches), contains(pattern("/f?o"), pattern("/fo?")));
}
@Test
public void findNoMatch() {
this.registry.register("/foo/{bar}", new Object());
assertThat(this.registry.findMatches("/other"), hasSize(0));
PathContainer path = PathContainer.parse("/other", StandardCharsets.UTF_8);
assertThat(this.registry.findMatches(path), hasSize(0));
}
@Test
@@ -88,7 +93,8 @@ public class PathPatternRegistryTests {
this.registry.register("/foo/{*baz}", new Object());
this.registry.register("/foo/bar/baz", new Object());
this.registry.register("/foo/bar/{baz}", new Object());
Set<PathMatchResult<Object>> matches = this.registry.findMatches("/foo/bar/baz");
PathContainer path = PathContainer.parse("/foo/bar/baz", StandardCharsets.UTF_8);
Set<PathMatchResult<Object>> matches = this.registry.findMatches(path);
assertThat(toPatterns(matches), contains(pattern("/foo/bar/baz"), pattern("/foo/bar/{baz}"),
pattern("/foo/{*baz}")));
}

View File

@@ -16,6 +16,7 @@
package org.springframework.web.reactive.resource;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
@@ -32,6 +33,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.server.reactive.PathContainer;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@@ -73,7 +75,8 @@ public class ResourceUrlProviderTests {
@Test
public void getStaticResourceUrl() {
String url = this.urlProvider.getForLookupPath("/resources/foo.css").block(Duration.ofSeconds(5));
PathContainer path = PathContainer.parse("/resources/foo.css", StandardCharsets.UTF_8);
String url = this.urlProvider.getForLookupPath(path).block(Duration.ofSeconds(5));
assertEquals("/resources/foo.css", url);
}
@@ -102,7 +105,8 @@ public class ResourceUrlProviderTests {
resolvers.add(new PathResourceResolver());
this.handler.setResourceResolvers(resolvers);
String url = this.urlProvider.getForLookupPath("/resources/foo.css").block(Duration.ofSeconds(5));
PathContainer path = PathContainer.parse("/resources/foo.css", StandardCharsets.UTF_8);
String url = this.urlProvider.getForLookupPath(path).block(Duration.ofSeconds(5));
assertEquals("/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css", url);
}
@@ -123,7 +127,8 @@ public class ResourceUrlProviderTests {
this.handlerMap.put("/resources/*.css", otherHandler);
this.urlProvider.setHandlerMap(this.handlerMap);
String url = this.urlProvider.getForLookupPath("/resources/foo.css").block(Duration.ofSeconds(5));
PathContainer path = PathContainer.parse("/resources/foo.css", StandardCharsets.UTF_8);
String url = this.urlProvider.getForLookupPath(path).block(Duration.ofSeconds(5));
assertEquals("/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css", url);
}