WebFlux compiles after PathPattern/Container changes
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user