WebFlux compiles after PathPattern/Container changes

This commit is contained in:
Rossen Stoyanchev
2017-06-30 11:03:36 -04:00
parent 26448a0ebc
commit 8581afa621
9 changed files with 220 additions and 269 deletions

View File

@@ -343,7 +343,7 @@ public abstract class RequestPredicates {
boolean match = this.pattern.matches(path);
traceMatch("Pattern", this.pattern.getPatternString(), path, match);
if (match) {
mergeTemplateVariables(request, this.pattern.matchAndExtract(request.path()));
mergeTemplateVariables(request, this.pattern.matchAndExtract(request.path()).getUriVariables());
return true;
}
else {
@@ -355,7 +355,7 @@ public abstract class RequestPredicates {
public Optional<ServerRequest> nest(ServerRequest request) {
return Optional.ofNullable(this.pattern.getPathRemaining(request.path()))
.map(info -> {
mergeTemplateVariables(request, info.getMatchingVariables());
mergeTemplateVariables(request, info.getUriVariables());
String path = info.getPathRemaining();
if (!path.startsWith("/")) {
path = "/" + path;

View File

@@ -119,7 +119,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
* the "other" instance as follows:
* <ul>
* <li>If there are patterns in both instances, combine the patterns in "this" with
* the patterns in "other" using {@link PathPattern#combine(String)}.
* the patterns in "other" using {@link PathPattern#combine(PathPattern)}.
* <li>If only one instance has patterns, use them.
* <li>If neither instance has patterns, use an empty String (i.e. "").
* </ul>
@@ -130,8 +130,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
if (!this.patterns.isEmpty() && !other.patterns.isEmpty()) {
for (PathPattern pattern1 : this.patterns) {
for (PathPattern pattern2 : other.patterns) {
String combinedPattern = pattern1.combine(pattern2.getPatternString());
combined.add(this.parser.parse(combinedPattern));
combined.add(pattern1.combine(pattern2));
}
}
}
@@ -166,7 +165,8 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
SortedSet<PathPattern> matches = getMatchingPatterns(lookupPath);
return matches.isEmpty() ? null : new PatternsRequestCondition(new ArrayList<>(matches), this.parser);
return matches.isEmpty() ? null : new PatternsRequestCondition(
new ArrayList<PathPattern>(matches), this.parser);
}
/**

View File

@@ -17,18 +17,14 @@
package org.springframework.web.reactive.result.method;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
import org.springframework.http.HttpHeaders;
@@ -36,9 +32,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.result.condition.NameValueExpression;
@@ -113,31 +107,25 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
PathPattern bestPattern;
Map<String, String> uriVariables;
Map<String, MultiValueMap<String, String>> matrixVariables;
Set<PathPattern> patterns = info.getPatternsCondition().getPatterns();
if (patterns.isEmpty()) {
bestPattern = getPathPatternParser().parse(lookupPath);
uriVariables = Collections.emptyMap();
matrixVariables = Collections.emptyMap();
}
else {
bestPattern = patterns.iterator().next();
uriVariables = bestPattern.matchAndExtract(lookupPath);
}
// Let URI vars be stripped of semicolon content..
Map<String, MultiValueMap<String, String>> matrixVars = extractMatrixVariables(exchange, uriVariables);
exchange.getAttributes().put(MATRIX_VARIABLES_ATTRIBUTE, matrixVars);
// Now decode URI variables
if (!uriVariables.isEmpty()) {
uriVariables = uriVariables.entrySet().stream().collect(Collectors.toMap(
Entry::getKey, e -> StringUtils.uriDecode(e.getValue(), StandardCharsets.UTF_8)
));
PathPattern.PathMatchResult result = bestPattern.matchAndExtract(lookupPath);
uriVariables = result.getUriVariables();
matrixVariables = result.getMatrixVariables();
}
exchange.getAttributes().put(BEST_MATCHING_HANDLER_ATTRIBUTE, handlerMethod);
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);
exchange.getAttributes().put(MATRIX_VARIABLES_ATTRIBUTE, matrixVariables);
if (!info.getProducesCondition().getProducibleMediaTypes().isEmpty()) {
Set<MediaType> mediaTypes = info.getProducesCondition().getProducibleMediaTypes();
@@ -145,62 +133,6 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
}
}
private Map<String, MultiValueMap<String, String>> extractMatrixVariables(
ServerWebExchange exchange, Map<String, String> uriVariables) {
Map<String, MultiValueMap<String, String>> result = new LinkedHashMap<>();
for (Entry<String, String> uriVar : uriVariables.entrySet()) {
String uriVarValue = uriVar.getValue();
int equalsIndex = uriVarValue.indexOf('=');
if (equalsIndex == -1) {
continue;
}
String semicolonContent;
int semicolonIndex = uriVarValue.indexOf(';');
if ((semicolonIndex == -1) || (semicolonIndex == 0) || (equalsIndex < semicolonIndex)) {
semicolonContent = uriVarValue;
}
else {
semicolonContent = uriVarValue.substring(semicolonIndex + 1);
uriVariables.put(uriVar.getKey(), uriVarValue.substring(0, semicolonIndex));
}
result.put(uriVar.getKey(), parseMatrixVariables(exchange, semicolonContent));
}
return result;
}
private static MultiValueMap<String, String> parseMatrixVariables(ServerWebExchange exchange,
String semicolonContent) {
MultiValueMap<String, String> vars = new LinkedMultiValueMap<>();
if (!StringUtils.hasText(semicolonContent)) {
return vars;
}
StringTokenizer pairs = new StringTokenizer(semicolonContent, ";");
while (pairs.hasMoreTokens()) {
String pair = pairs.nextToken();
int index = pair.indexOf('=');
if (index != -1) {
String name = pair.substring(0, index);
String rawValue = pair.substring(index + 1);
for (String value : StringUtils.commaDelimitedListToStringArray(rawValue)) {
vars.add(name, value);
}
}
else {
vars.add(pair, "");
}
}
MultiValueMap<String, String> decoded = new LinkedMultiValueMap<>(vars.size());
vars.forEach((key, values) -> values.forEach(value -> {
String decodedValue = StringUtils.uriDecode(value, StandardCharsets.UTF_8);
decoded.add(key, decodedValue);
}));
return decoded;
}
/**
* Iterate all RequestMappingInfos once again, look if any match by URL at
* least and raise exceptions accordingly.

View File

@@ -50,7 +50,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.springframework.web.reactive.function.BodyExtractors.toMono;
/**

View File

@@ -294,41 +294,19 @@ public class RequestMappingInfoHandlerMappingTests {
assertEquals(Arrays.asList("red", "blue", "green"), matrixVariables.get("colors"));
assertEquals("2012", matrixVariables.getFirst("year"));
assertEquals("cars", uriVariables.get("cars"));
exchange = get("/cars;colors=red,blue,green;year=2012").toExchange();
handleMatch(exchange, "/{cars:[^;]+}{params}");
matrixVariables = getMatrixVariables(exchange, "params");
uriVariables = getUriTemplateVariables(exchange);
assertNotNull(matrixVariables);
assertEquals(Arrays.asList("red", "blue", "green"), matrixVariables.get("colors"));
assertEquals("2012", matrixVariables.getFirst("year"));
assertEquals("cars", uriVariables.get("cars"));
assertEquals(";colors=red,blue,green;year=2012", uriVariables.get("params"));
exchange = get("/cars").toExchange();
handleMatch(exchange, "/{cars:[^;]+}{params}");
matrixVariables = getMatrixVariables(exchange, "params");
uriVariables = getUriTemplateVariables(exchange);
assertNull(matrixVariables);
assertEquals("cars", uriVariables.get("cars"));
assertEquals("", uriVariables.get("params"));
}
@Test
public void handleMatchMatrixVariablesDecoding() throws Exception {
ServerWebExchange exchange = method(HttpMethod.GET, URI.create("/path;mvar=a%2fb")).toExchange();
handleMatch(exchange, "/path{filter}");
handleMatch(exchange, "/{filter}");
MultiValueMap<String, String> matrixVariables = getMatrixVariables(exchange, "filter");
Map<String, String> uriVariables = getUriTemplateVariables(exchange);
assertNotNull(matrixVariables);
assertEquals(Collections.singletonList("a/b"), matrixVariables.get("mvar"));
assertEquals(";mvar=a/b", uriVariables.get("filter"));
assertEquals("path", uriVariables.get("filter"));
}