Revert Path Pattern changes in WebFlux

Issue: SPR-14544
This commit is contained in:
Brian Clozel
2017-02-10 18:08:43 +01:00
parent 5b98a54c9b
commit fa4202f1bd
22 changed files with 790 additions and 955 deletions

View File

@@ -19,10 +19,8 @@ package org.springframework.web.reactive.config;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
@@ -53,7 +51,6 @@ import org.springframework.validation.Validator;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.bind.support.WebExchangeDataBinder;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
@@ -73,7 +70,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM;
@@ -106,9 +102,9 @@ public class WebFluxConfigurationSupportTests {
assertEquals(0, mapping.getOrder());
assertFalse(mapping.getPatternRegistry().useSuffixPatternMatch());
assertThat(mapping.getPatternRegistry().getFileExtensions(), Matchers.empty());
assertTrue(mapping.getPatternRegistry().useTrailingSlashMatch());
assertTrue(mapping.useSuffixPatternMatch());
assertTrue(mapping.useTrailingSlashMatch());
assertTrue(mapping.useRegisteredSuffixPatternMatch());
name = "webFluxContentTypeResolver";
RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class);
@@ -130,9 +126,8 @@ public class WebFluxConfigurationSupportTests {
RequestMappingHandlerMapping mapping = context.getBean(name, RequestMappingHandlerMapping.class);
assertNotNull(mapping);
assertFalse(mapping.getPatternRegistry().useTrailingSlashMatch());
assertTrue(mapping.getPatternRegistry().useSuffixPatternMatch());
assertThat(mapping.getPatternRegistry().getFileExtensions(), Matchers.contains(".json", ".xml"));
assertFalse(mapping.useSuffixPatternMatch());
assertFalse(mapping.useTrailingSlashMatch());
}
@Test
@@ -267,6 +262,7 @@ public class WebFluxConfigurationSupportTests {
assertEquals(Ordered.LOWEST_PRECEDENCE - 1, handlerMapping.getOrder());
assertNotNull(handlerMapping.getPathHelper());
assertNotNull(handlerMapping.getPathMatcher());
SimpleUrlHandlerMapping urlHandlerMapping = (SimpleUrlHandlerMapping) handlerMapping;
WebHandler webHandler = (WebHandler) urlHandlerMapping.getUrlMap().get("/images/**");
@@ -311,15 +307,8 @@ public class WebFluxConfigurationSupportTests {
@Override
public void configurePathMatching(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
configurer.setUseTrailingSlashMatch(false);
configurer.setUseSuffixPatternMatch(true);
configurer.setUseRegisteredSuffixPatternMatch(true);
}
@Override
protected void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
builder.mediaType("json", MediaType.APPLICATION_JSON);
builder.mediaType("xml", MediaType.APPLICATION_XML);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,12 +55,11 @@ public class SimpleUrlHandlerMappingTests {
Object mainController = wac.getBean("mainController");
Object otherController = wac.getBean("otherController");
// TODO: direct matches have been removed, path within mapping is indeed ""
testUrl("/welcome.html", mainController, handlerMapping, "");
testUrl("/welcome.html", mainController, handlerMapping, "/welcome.html");
testUrl("/welcome.x", otherController, handlerMapping, "welcome.x");
testUrl("/welcome/", otherController, handlerMapping, "welcome");
testUrl("/show.html", mainController, handlerMapping, "");
testUrl("/bookseats.html", mainController, handlerMapping, "");
testUrl("/show.html", mainController, handlerMapping, "/show.html");
testUrl("/bookseats.html", mainController, handlerMapping, "/bookseats.html");
}
@Test
@@ -75,10 +74,10 @@ public class SimpleUrlHandlerMappingTests {
testUrl("welcome.html", null, handlerMapping, null);
testUrl("/pathmatchingAA.html", mainController, handlerMapping, "pathmatchingAA.html");
testUrl("/pathmatchingA.html", null, handlerMapping, null);
testUrl("/administrator/pathmatching.html", mainController, handlerMapping, "");
testUrl("/administrator/pathmatching.html", mainController, handlerMapping, "/administrator/pathmatching.html");
testUrl("/administrator/test/pathmatching.html", mainController, handlerMapping, "test/pathmatching.html");
testUrl("/administratort/pathmatching.html", null, handlerMapping, null);
testUrl("/administrator/another/bla.xml", mainController, handlerMapping, "");
testUrl("/administrator/another/bla.xml", mainController, handlerMapping, "/administrator/another/bla.xml");
testUrl("/administrator/another/bla.gif", null, handlerMapping, null);
testUrl("/administrator/test/testlastbit", mainController, handlerMapping, "test/testlastbit");
testUrl("/administrator/test/testla", null, handlerMapping, null);
@@ -90,7 +89,7 @@ public class SimpleUrlHandlerMappingTests {
testUrl("/XpathXXmatching.html", null, handlerMapping, null);
testUrl("/XXpathmatching.html", null, handlerMapping, null);
testUrl("/show12.html", mainController, handlerMapping, "show12.html");
testUrl("/show123.html", mainController, handlerMapping, "");
testUrl("/show123.html", mainController, handlerMapping, "/show123.html");
testUrl("/show1.html", mainController, handlerMapping, "show1.html");
testUrl("/reallyGood-test-is-this.jpeg", mainController, handlerMapping, "reallyGood-test-is-this.jpeg");
testUrl("/reallyGood-tst-is-this.jpeg", null, handlerMapping, null);

View File

@@ -39,7 +39,6 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.util.patterns.PathPatternParser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,8 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.util.patterns.PathPatternParser;
import org.springframework.web.server.session.DefaultWebSessionManager;
import org.springframework.web.server.session.WebSessionManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -136,8 +137,7 @@ public class ResourceUrlProviderTests {
context.refresh();
ResourceUrlProvider urlProviderBean = context.getBean(ResourceUrlProvider.class);
assertThat(urlProviderBean.getHandlerMap(),
Matchers.hasKey(new PathPatternParser().parse("/resources/**")));
assertThat(urlProviderBean.getHandlerMap(), Matchers.hasKey("/resources/**"));
assertFalse(urlProviderBean.isAutodetect());
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package org.springframework.web.reactive.result.condition;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import org.junit.Test;
@@ -28,8 +27,6 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.util.patterns.PathPattern;
import org.springframework.web.util.patterns.PathPatternRegistry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -45,14 +42,13 @@ public class PatternsRequestConditionTests {
@Test
public void prependSlash() {
PatternsRequestCondition c = new PatternsRequestCondition("foo");
assertEquals("/foo", c.getPatterns().iterator().next().getPatternString());
assertEquals("/foo", c.getPatterns().iterator().next());
}
@Test
public void prependNonEmptyPatternsOnly() {
PatternsRequestCondition c = new PatternsRequestCondition("");
assertEquals("Do not prepend empty patterns (SPR-8255)", "",
c.getPatterns().iterator().next().getPatternString());
assertEquals("Do not prepend empty patterns (SPR-8255)", "", c.getPatterns().iterator().next());
}
@Test
@@ -117,14 +113,13 @@ public class PatternsRequestConditionTests {
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
assertNotNull(match);
assertEquals("/{foo}", match.getPatterns().iterator().next().getPatternString());
assertEquals("/{foo}.*", match.getPatterns().iterator().next());
condition = new PatternsRequestCondition(new String[] {"/foo"}, null,
createPatternRegistry(true, false, null));
condition = new PatternsRequestCondition(new String[] {"/{foo}"}, null, null, false, false, null);
match = condition.getMatchingCondition(exchange);
assertNotNull(match);
assertEquals("/foo.*", match.getPatterns().iterator().next().getPatternString());
assertEquals("/{foo}", match.getPatterns().iterator().next());
}
// SPR-8410
@@ -133,33 +128,28 @@ public class PatternsRequestConditionTests {
public void matchSuffixPatternUsingFileExtensions() throws Exception {
String[] patterns = new String[] {"/jobs/{jobName}"};
Set<String> extensions = Collections.singleton("json");
PatternsRequestCondition condition = new PatternsRequestCondition(patterns, null,
createPatternRegistry(true, false, extensions));
PatternsRequestCondition condition = new PatternsRequestCondition(patterns, null, null, true, false, extensions);
ServerWebExchange exchange = createExchange("/jobs/my.job");
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
assertNotNull(match);
assertEquals("/jobs/{jobName}", match.getPatterns().iterator().next().getPatternString());
assertEquals("/jobs/{jobName}", match.getPatterns().iterator().next());
exchange = createExchange("/jobs/my.job.json");
match = condition.getMatchingCondition(exchange);
assertNotNull(match);
Iterator<PathPattern> matchedPatterns = match.getPatterns().iterator();
assertEquals("/jobs/{jobName}", matchedPatterns.next().getPatternString());
assertEquals("/jobs/{jobName}.json", matchedPatterns.next().getPatternString());
assertEquals("/jobs/{jobName}.json", match.getPatterns().iterator().next());
}
@Test
public void matchSuffixPatternUsingFileExtensions2() throws Exception {
PatternsRequestCondition condition1 = new PatternsRequestCondition(
new String[] {"/prefix"}, null,
createPatternRegistry(true, false, Collections.singleton("json")));
new String[] {"/prefix"}, null, null, true, false, Collections.singleton("json"));
PatternsRequestCondition condition2 = new PatternsRequestCondition(
new String[] {"/suffix"}, null,
createPatternRegistry(true, false, null));
new String[] {"/suffix"}, null, null, true, false, null);
PatternsRequestCondition combined = condition1.combine(condition2);
@@ -176,22 +166,20 @@ public class PatternsRequestConditionTests {
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
assertNull("Should not match by default", match);
assertNotNull(match);
assertEquals("Should match by default", "/foo/", match.getPatterns().iterator().next());
condition = new PatternsRequestCondition(new String[] {"/foo"}, null,
createPatternRegistry(false, true, null));
condition = new PatternsRequestCondition(new String[] {"/foo"}, null, null, false, true, null);
match = condition.getMatchingCondition(exchange);
assertNotNull(match);
assertEquals("Trailing slash should be insensitive to useSuffixPatternMatch settings (SPR-6164, SPR-5636)",
"/foo/", match.getPatterns().iterator().next().getPatternString());
"/foo/", match.getPatterns().iterator().next());
condition = new PatternsRequestCondition(new String[] {"/foo"}, null,
createPatternRegistry(true, true, null));
condition = new PatternsRequestCondition(new String[] {"/foo"}, null, null, false, false, null);
match = condition.getMatchingCondition(exchange);
assertNotNull(match);
assertEquals("/foo/", match.getPatterns().iterator().next().getPatternString());
assertNull(match);
}
@Test
@@ -228,8 +216,8 @@ public class PatternsRequestConditionTests {
PatternsRequestCondition match1 = c1.getMatchingCondition(exchange);
PatternsRequestCondition match2 = c2.getMatchingCondition(exchange);
assertNull(match1);
assertEquals("/*.html", match2.getPatterns().iterator().next().getPatternString());
assertNotNull(match1);
assertEquals(1, match1.compareTo(match2, exchange));
}
@@ -238,13 +226,4 @@ public class PatternsRequestConditionTests {
return new DefaultServerWebExchange(request, new MockServerHttpResponse());
}
private PathPatternRegistry createPatternRegistry(boolean useSuffixPatternMatch, boolean useTrailingSlashMatch,
Set<String> extensions) {
PathPatternRegistry registry = new PathPatternRegistry();
registry.setUseSuffixPatternMatch(useSuffixPatternMatch);
registry.setUseTrailingSlashMatch(useTrailingSlashMatch);
registry.setFileExtensions(extensions);
return registry;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,9 +20,8 @@ import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.junit.Before;
import org.junit.Test;
@@ -34,16 +33,14 @@ import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.util.PathMatcher;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.session.MockWebSessionManager;
import org.springframework.web.server.session.WebSessionManager;
import org.springframework.web.util.patterns.PathPattern;
import org.springframework.web.util.patterns.PathPatternComparator;
import org.springframework.web.util.patterns.PathPatternParser;
import org.springframework.web.util.patterns.PatternComparatorConsideringPath;
import org.springframework.web.util.ParsingPathMatcher;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -55,8 +52,6 @@ import static org.junit.Assert.assertNull;
*/
public class HandlerMethodMappingTests {
private PathPatternParser patternParser = new PathPatternParser();
private AbstractHandlerMethodMapping<String> mapping;
private MyHandler handler;
@@ -77,13 +72,13 @@ public class HandlerMethodMappingTests {
@Test(expected = IllegalStateException.class)
public void registerDuplicates() {
this.mapping.registerMapping("/foo", this.handler, this.method1);
this.mapping.registerMapping("/foo", this.handler, this.method2);
this.mapping.registerMapping("foo", this.handler, this.method1);
this.mapping.registerMapping("foo", this.handler, this.method2);
}
@Test
public void directMatch() throws Exception {
String key = "/foo";
String key = "foo";
this.mapping.registerMapping(key, this.handler, this.method1);
Mono<Object> result = this.mapping.getHandler(createExchange(HttpMethod.GET, key));
@@ -115,26 +110,32 @@ public class HandlerMethodMappingTests {
this.mapping.registerMapping(key1, this.handler, this.method1);
this.mapping.registerMapping(key2, this.handler, this.method2);
HandlerMethod match = this.mapping.getMappingRegistry().getMappings().get(key1);
assertNotNull(match);
List directUrlMatches = this.mapping.getMappingRegistry().getMappingsByUrl(key1);
assertNotNull(directUrlMatches);
assertEquals(1, directUrlMatches.size());
assertEquals(key1, directUrlMatches.get(0));
}
@Test
public void registerMappingWithSameMethodAndTwoHandlerInstances() throws Exception {
String key1 = "/foo";
String key2 = "/bar";
String key1 = "foo";
String key2 = "bar";
MyHandler handler1 = new MyHandler();
MyHandler handler2 = new MyHandler();
this.mapping.registerMapping(key1, handler1, this.method1);
this.mapping.registerMapping(key2, handler2, this.method1);
HandlerMethod match = this.mapping.getMappingRegistry().getMappings().get(key1);
assertNotNull(match);
List directUrlMatches = this.mapping.getMappingRegistry().getMappingsByUrl(key1);
assertNotNull(directUrlMatches);
assertEquals(1, directUrlMatches.size());
assertEquals(key1, directUrlMatches.get(0));
}
@Test
public void unregisterMapping() throws Exception {
String key = "/foo";
String key = "foo";
this.mapping.registerMapping(key, this.handler, this.method1);
Mono<Object> result = this.mapping.getHandler(createExchange(HttpMethod.GET, key));
@@ -144,7 +145,7 @@ public class HandlerMethodMappingTests {
result = this.mapping.getHandler(createExchange(HttpMethod.GET, key));
assertNull(result.block());
assertNull(this.mapping.getMappingRegistry().getMappings().get(key));
assertNull(this.mapping.getMappingRegistry().getMappingsByUrl(key));
}
@@ -157,7 +158,7 @@ public class HandlerMethodMappingTests {
private static class MyHandlerMethodMapping extends AbstractHandlerMethodMapping<String> {
private PathPatternParser patternParser = new PathPatternParser();
private PathMatcher pathMatcher = new ParsingPathMatcher();
@Override
protected boolean isHandler(Class<?> beanType) {
@@ -172,27 +173,19 @@ public class HandlerMethodMappingTests {
@Override
protected Set<String> getMappingPathPatterns(String key) {
return Collections.singleton(key);
return (this.pathMatcher.isPattern(key) ? Collections.emptySet() : Collections.singleton(key));
}
@Override
protected String getMatchingMapping(String pattern, ServerWebExchange exchange) {
String lookupPath = exchange.getRequest().getURI().getPath();
PathPattern pathPattern = this.patternParser.parse(pattern);
return (pathPattern.matches(lookupPath) ? pattern : null);
return (this.pathMatcher.match(pattern, lookupPath) ? pattern : null);
}
@Override
protected Comparator<String> getMappingComparator(ServerWebExchange exchange) {
String lookupPath = exchange.getRequest().getURI().getPath();
PatternComparatorConsideringPath comparator = new PatternComparatorConsideringPath(lookupPath);
return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return comparator.compare(patternParser.parse(o1), patternParser.parse(o2));
}
};
return this.pathMatcher.getPatternComparator(lookupPath);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,9 +26,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@@ -61,8 +59,6 @@ import org.springframework.web.server.ServerWebInputException;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.support.HttpRequestPathHelper;
import org.springframework.web.util.patterns.PathPattern;
import org.springframework.web.util.patterns.PathPatternRegistry;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
@@ -85,6 +81,7 @@ public class RequestMappingInfoHandlerMappingTests {
private ServerHttpRequest request;
@Before
public void setUp() throws Exception {
this.handlerMapping = new TestRequestMappingInfoHandlerMapping();
@@ -98,8 +95,7 @@ public class RequestMappingInfoHandlerMappingTests {
RequestMappingInfo info = paths(patterns).build();
Set<String> actual = this.handlerMapping.getMappingPathPatterns(info);
assertThat(actual, Matchers.containsInAnyOrder("/foo/*", "/foo", "/bar/*", "/bar",
"/foo/*/", "/foo/", "/bar/*/", "/bar/"));
assertEquals(new HashSet<>(Arrays.asList(patterns)), actual);
}
@Test
@@ -127,9 +123,6 @@ public class RequestMappingInfoHandlerMappingTests {
}
@Test
@Ignore
// TODO: for "" patterns, should we generate the "/" variant (and break SPR-8255)
// or handle matching in a different way? Here, setTrailingSlashMatch is set to false for tests
public void getHandlerEmptyPathMatch() throws Exception {
String[] patterns = new String[] {""};
Method expected = resolveMethod(new TestController(), patterns, null, null);
@@ -189,7 +182,7 @@ public class RequestMappingInfoHandlerMappingTests {
assertError(mono, UnsupportedMediaTypeStatusException.class,
ex -> assertEquals("Request failure [status: 415, " +
"reason: \"Invalid mime type \"bogus\": does not contain '/'\"]",
"reason: \"Invalid mime type \"bogus\": does not contain '/'\"]",
ex.getMessage()));
}
@@ -235,8 +228,7 @@ public class RequestMappingInfoHandlerMappingTests {
exchange.getAttributes().get(name));
}
@Test
@SuppressWarnings("unchecked")
@Test @SuppressWarnings("unchecked")
public void handleMatchUriTemplateVariables() throws Exception {
String lookupPath = "/1/2";
this.request = MockServerHttpRequest.get(lookupPath).build();
@@ -282,9 +274,7 @@ public class RequestMappingInfoHandlerMappingTests {
ServerWebExchange exchange = createExchange();
this.handlerMapping.handleMatch(key, "/1/2", exchange);
PathPattern pattern = (PathPattern) exchange.getAttributes()
.get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
assertEquals("/{path1}/2", pattern.getPatternString());
assertEquals("/{path1}/2", exchange.getAttributes().get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE));
}
@Test
@@ -295,9 +285,7 @@ public class RequestMappingInfoHandlerMappingTests {
this.handlerMapping.handleMatch(key, "/1/2", exchange);
PathPattern pattern = (PathPattern) exchange.getAttributes()
.get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
assertEquals("/1/2", pattern.getPatternString());
assertEquals("/1/2", exchange.getAttributes().get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE));
}
@Test
@@ -368,7 +356,7 @@ public class RequestMappingInfoHandlerMappingTests {
}
@SuppressWarnings("unchecked")
private <T> void assertError(Mono<Object> mono, final Class<T> exceptionClass, final Consumer<T> consumer) {
private <T> void assertError(Mono<Object> mono, final Class<T> exceptionClass, final Consumer<T> consumer) {
StepVerifier.create(mono)
.consumeErrorWith(error -> {
@@ -467,11 +455,11 @@ public class RequestMappingInfoHandlerMappingTests {
public void foo() {
}
@GetMapping(path = "/foo", params = "p")
@GetMapping(path = "/foo", params="p")
public void fooParam() {
}
@RequestMapping(path = "/ba*", method = {GET, HEAD})
@RequestMapping(path = "/ba*", method = { GET, HEAD })
public void bar() {
}
@@ -479,31 +467,31 @@ public class RequestMappingInfoHandlerMappingTests {
public void empty() {
}
@PutMapping(path = "/person/{id}", consumes = "application/xml")
@PutMapping(path = "/person/{id}", consumes="application/xml")
public void consumes(@RequestBody String text) {
}
@RequestMapping(path = "/persons", produces = "application/xml")
@RequestMapping(path = "/persons", produces="application/xml")
public String produces() {
return "";
}
@RequestMapping(path = "/params", params = "foo=bar")
@RequestMapping(path = "/params", params="foo=bar")
public String param() {
return "";
}
@RequestMapping(path = "/params", params = "bar=baz")
@RequestMapping(path = "/params", params="bar=baz")
public String param2() {
return "";
}
@RequestMapping(path = "/content", produces = "application/xml")
@RequestMapping(path = "/content", produces="application/xml")
public String xmlContent() {
return "";
}
@RequestMapping(path = "/content", produces = "!application/xml")
@RequestMapping(path = "/content", produces="!application/xml")
public String nonXmlContent() {
return "";
}
@@ -544,12 +532,11 @@ public class RequestMappingInfoHandlerMappingTests {
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMapping annot = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
if (annot != null) {
PathPatternRegistry pathPatternRegistry = new PathPatternRegistry();
pathPatternRegistry.setUseSuffixPatternMatch(true);
pathPatternRegistry.setUseTrailingSlashMatch(true);
BuilderConfiguration options = new BuilderConfiguration();
options.setPathHelper(getPathHelper());
options.setPathPatternRegistry(pathPatternRegistry);
options.setPathMatcher(getPathMatcher());
options.setSuffixPatternMatch(true);
options.setTrailingSlashMatch(true);
return paths(annot.value()).methods(annot.method())
.params(annot.params()).headers(annot.headers())
.consumes(annot.consumes()).produces(annot.produces())

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,10 +22,10 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
@@ -40,12 +40,16 @@ import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.reactive.accept.MappingContentTypeResolver;
import org.springframework.web.reactive.result.method.RequestMappingInfo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Unit tests for {@link RequestMappingHandlerMapping}.
@@ -64,6 +68,64 @@ public class RequestMappingHandlerMappingTests {
this.handlerMapping.setApplicationContext(wac);
}
@Test
public void useRegisteredSuffixPatternMatch() {
assertTrue(this.handlerMapping.useSuffixPatternMatch());
assertTrue(this.handlerMapping.useRegisteredSuffixPatternMatch());
MappingContentTypeResolver contentTypeResolver = mock(MappingContentTypeResolver.class);
when(contentTypeResolver.getKeys()).thenReturn(Collections.singleton("json"));
this.handlerMapping.setContentTypeResolver(contentTypeResolver);
this.handlerMapping.afterPropertiesSet();
assertTrue(this.handlerMapping.useSuffixPatternMatch());
assertTrue(this.handlerMapping.useRegisteredSuffixPatternMatch());
assertEquals(Collections.singleton("json"), this.handlerMapping.getFileExtensions());
}
@Test
public void useRegisteredSuffixPatternMatchInitialization() {
MappingContentTypeResolver contentTypeResolver = mock(MappingContentTypeResolver.class);
when(contentTypeResolver.getKeys()).thenReturn(Collections.singleton("json"));
final Set<String> actualExtensions = new HashSet<>();
RequestMappingHandlerMapping localHandlerMapping = new RequestMappingHandlerMapping() {
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
actualExtensions.addAll(getFileExtensions());
return super.getMappingForMethod(method, handlerType);
}
};
this.wac.registerSingleton("testController", ComposedAnnotationController.class);
this.wac.refresh();
localHandlerMapping.setContentTypeResolver(contentTypeResolver);
localHandlerMapping.setUseRegisteredSuffixPatternMatch(true);
localHandlerMapping.setApplicationContext(this.wac);
localHandlerMapping.afterPropertiesSet();
assertEquals(Collections.singleton("json"), actualExtensions);
}
@Test
public void useSuffixPatternMatch() {
assertTrue(this.handlerMapping.useSuffixPatternMatch());
assertTrue(this.handlerMapping.useRegisteredSuffixPatternMatch());
this.handlerMapping.setUseSuffixPatternMatch(false);
assertFalse(this.handlerMapping.useSuffixPatternMatch());
this.handlerMapping.setUseRegisteredSuffixPatternMatch(false);
assertFalse("'false' registeredSuffixPatternMatch shouldn't impact suffixPatternMatch",
this.handlerMapping.useSuffixPatternMatch());
this.handlerMapping.setUseRegisteredSuffixPatternMatch(true);
assertTrue("'true' registeredSuffixPatternMatch should enable suffixPatternMatch",
this.handlerMapping.useSuffixPatternMatch());
}
@Test
public void resolveEmbeddedValuesInPatterns() {
this.handlerMapping.setEmbeddedValueResolver(
@@ -135,10 +197,9 @@ public class RequestMappingHandlerMappingTests {
assertNotNull(info);
Set<String> paths = info.getPatternsCondition().getPatterns()
.stream().map(p -> p.getPatternString()).collect(Collectors.toSet());
assertEquals(2, paths.size());
assertThat(paths, Matchers.containsInAnyOrder(path, path + "/"));
Set<String> paths = info.getPatternsCondition().getPatterns();
assertEquals(1, paths.size());
assertEquals(path, paths.iterator().next());
Set<RequestMethod> methods = info.getMethodsCondition().getMethods();
assertEquals(1, methods.size());