Skip to content

Commit b312eca

Browse files
committed
Deprecate and set trailingSlash option to false
Closes gh-28552
1 parent d2e27ad commit b312eca

File tree

27 files changed

+84
-82
lines changed

27 files changed

+84
-82
lines changed

spring-test/src/main/java/org/springframework/test/web/servlet/client/MockMvcWebTestClient.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -358,7 +358,10 @@ ControllerSpec mappedInterceptors(
358358
* Whether to match trailing slashes.
359359
* <p>This is delegated to
360360
* {@link StandaloneMockMvcBuilder#setUseTrailingSlashPatternMatch(boolean)}.
361+
* @deprecated as of 6.0, see
362+
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
361363
*/
364+
@Deprecated
362365
ControllerSpec useTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch);
363366

364367
/**

spring-test/src/main/java/org/springframework/test/web/servlet/client/StandaloneMockMvcSpec.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -152,6 +152,7 @@ public StandaloneMockMvcSpec patternParser(PathPatternParser parser) {
152152
return this;
153153
}
154154

155+
@SuppressWarnings("deprecation")
155156
@Override
156157
public StandaloneMockMvcSpec useTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch) {
157158
this.mockMvcBuilder.setUseTrailingSlashPatternMatch(useTrailingSlashPatternMatch);

spring-test/src/main/java/org/springframework/test/web/servlet/setup/StandaloneMockMvcBuilder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,10 @@ public StandaloneMockMvcBuilder setUseSuffixPatternMatch(boolean useSuffixPatter
343343
/**
344344
* Whether to match to URLs irrespective of the presence of a trailing slash.
345345
* If enabled a method mapped to "/users" also matches to "/users/".
346-
* <p>The default value is {@code true}.
346+
* @deprecated as of 6.0, see
347+
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
347348
*/
349+
@Deprecated
348350
public StandaloneMockMvcBuilder setUseTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch) {
349351
this.useTrailingSlashPatternMatch = useTrailingSlashPatternMatch;
350352
return this;

spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/FormContentTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ public void formContentIsNotDuplicated() throws Exception {
5050
@RestController
5151
private static class Spr15753Controller {
5252

53-
@PutMapping
53+
@PutMapping("/")
5454
public String test(Data d) {
5555
return String.format("d1:%s, d2:%s.", d.getD1(), d.getD2());
5656
}

spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -150,6 +150,7 @@ public class PathPattern implements Comparable<PathPattern> {
150150
private boolean catchAll = false;
151151

152152

153+
@SuppressWarnings("deprecation")
153154
PathPattern(String patternText, PathPatternParser parser, @Nullable PathElement head) {
154155
this.patternString = patternText;
155156
this.parser = parser;

spring-web/src/main/java/org/springframework/web/util/pattern/PathPatternParser.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
3434
*/
3535
public class PathPatternParser {
3636

37-
private boolean matchOptionalTrailingSeparator = true;
37+
private boolean matchOptionalTrailingSeparator = false;
3838

3939
private boolean caseSensitive = true;
4040

@@ -48,15 +48,22 @@ public class PathPatternParser {
4848
* will also match request paths with a trailing slash. If set to
4949
* {@code false} a {@code PathPattern} will only match request paths with
5050
* a trailing slash.
51-
* <p>The default is {@code true}.
51+
* <p>The default was changed in 6.0 from {@code true} to {@code false} in
52+
* order to support the deprecation of the property.
53+
* @deprecated transparent support for trailing slashes is deprecated as of
54+
* 6.0 in favor of configuring explicit redirects through a proxy,
55+
* Servlet/web filter, or a controller.
5256
*/
57+
@Deprecated
5358
public void setMatchOptionalTrailingSeparator(boolean matchOptionalTrailingSeparator) {
5459
this.matchOptionalTrailingSeparator = matchOptionalTrailingSeparator;
5560
}
5661

5762
/**
5863
* Whether optional trailing slashing match is enabled.
64+
* @deprecated as of 6.0 together with {@link #setMatchOptionalTrailingSeparator(boolean)}.
5965
*/
66+
@Deprecated
6067
public boolean isMatchOptionalTrailingSeparator() {
6168
return this.matchOptionalTrailingSeparator;
6269
}

spring-web/src/main/java/org/springframework/web/util/pattern/PathPatternRouteMatcher.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -48,7 +48,6 @@ public class PathPatternRouteMatcher implements RouteMatcher {
4848
public PathPatternRouteMatcher() {
4949
this.parser = new PathPatternParser();
5050
this.parser.setPathOptions(PathContainer.Options.MESSAGE_ROUTE);
51-
this.parser.setMatchOptionalTrailingSeparator(false);
5251
}
5352

5453
/**

spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -99,6 +99,7 @@ private void assertNoMatch(PathPattern pp, String path) {
9999
assertThat(pp.matches(toPathContainer(path))).isFalse();
100100
}
101101

102+
@SuppressWarnings("deprecation")
102103
@Test
103104
public void optionalTrailingSeparators() {
104105
PathPattern pp;
@@ -438,6 +439,7 @@ public void multipleSeparatorsInPatternAndPath() {
438439
checkCapture("///{foo}///bar", "///one///bar", "foo", "one");
439440
}
440441

442+
@SuppressWarnings("deprecation")
441443
@Test
442444
public void wildcards() {
443445
checkMatches("/*/bar", "/foo/bar");
@@ -725,6 +727,7 @@ public void extractPathWithinPatternCustomSeparator() {
725727
}
726728

727729
@Test
730+
@SuppressWarnings("deprecation")
728731
public void extractUriTemplateVariables_spr15264() {
729732
PathPattern pp;
730733
pp = new PathPatternParser().parse("/{foo}");
@@ -1145,6 +1148,7 @@ private PathPattern.PathMatchInfo matchAndExtract(String pattern, String path) {
11451148
return parse(pattern).matchAndExtract(PathPatternTests.toPathContainer(path));
11461149
}
11471150

1151+
@SuppressWarnings("deprecation")
11481152
private PathPattern parse(String path) {
11491153
PathPatternParser pp = new PathPatternParser();
11501154
pp.setMatchOptionalTrailingSeparator(true);
@@ -1158,6 +1162,7 @@ public static PathContainer toPathContainer(String path) {
11581162
return PathContainer.parsePath(path);
11591163
}
11601164

1165+
@SuppressWarnings("deprecation")
11611166
private void checkMatches(String uriTemplate, String path) {
11621167
PathPatternParser parser = new PathPatternParser();
11631168
parser.setMatchOptionalTrailingSeparator(true);

spring-webflux/src/main/java/org/springframework/web/reactive/config/PathMatchConfigurer.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import java.util.function.Predicate;
2222

2323
import org.springframework.lang.Nullable;
24+
import org.springframework.web.util.pattern.PathPatternParser;
2425

2526
/**
2627
* Assist with configuring {@code HandlerMapping}'s with path matching options.
@@ -55,8 +56,12 @@ public PathMatchConfigurer setUseCaseSensitiveMatch(Boolean caseSensitiveMatch)
5556
/**
5657
* Whether to match to URLs irrespective of the presence of a trailing slash.
5758
* If enabled a method mapped to "/users" also matches to "/users/".
58-
* <p>The default value is {@code true}.
59+
* <p>The default was changed in 6.0 from {@code true} to {@code false} in
60+
* order to support the deprecation of the property.
61+
* @deprecated as of 6.0, see
62+
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
5963
*/
64+
@Deprecated
6065
public PathMatchConfigurer setUseTrailingSlashMatch(Boolean trailingSlashMatch) {
6166
this.trailingSlashMatch = trailingSlashMatch;
6267
return this;
@@ -83,6 +88,7 @@ public PathMatchConfigurer addPathPrefix(String prefix, Predicate<Class<?>> pred
8388

8489

8590
@Nullable
91+
@Deprecated
8692
protected Boolean isUseTrailingSlashMatch() {
8793
return this.trailingSlashMatch;
8894
}

spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -142,6 +142,7 @@ public RequestMappingHandlerMapping requestMappingHandlerMapping(
142142
return mapping;
143143
}
144144

145+
@SuppressWarnings("deprecation")
145146
private void configureAbstractHandlerMapping(AbstractHandlerMapping mapping, PathMatchConfigurer configurer) {
146147
mapping.setCorsConfigurations(getCorsConfigurations());
147148
Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();

spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
5858
LogDelegateFactory.getHiddenLog(HandlerMapping.class.getName() + ".Mappings");
5959

6060

61-
private final PathPatternParser patternParser;
61+
private final PathPatternParser patternParser = new PathPatternParser();
6262

6363
@Nullable
6464
private CorsConfigurationSource corsConfigurationSource;
@@ -71,11 +71,6 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
7171
private String beanName;
7272

7373

74-
public AbstractHandlerMapping() {
75-
this.patternParser = new PathPatternParser();
76-
}
77-
78-
7974
/**
8075
* Shortcut method for setting the same property on the underlying pattern
8176
* parser in use. For more details see:
@@ -98,7 +93,12 @@ public void setUseCaseSensitiveMatch(boolean caseSensitiveMatch) {
9893
* <li>{@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)} --
9994
* the trailing slash option, including its default value.
10095
* </ul>
96+
* <p>The default was changed in 6.0 from {@code true} to {@code false} in
97+
* order to support the deprecation of the property.
98+
* @deprecated as of 6.0, see
99+
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
101100
*/
101+
@Deprecated
102102
public void setUseTrailingSlashMatch(boolean trailingSlashMatch) {
103103
this.patternParser.setMatchOptionalTrailingSeparator(trailingSlashMatch);
104104
}

spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -110,7 +110,7 @@ public void requestMappingHandlerMapping() {
110110
PathPatternParser patternParser = mapping.getPathPatternParser();
111111
assertThat(patternParser).isNotNull();
112112
boolean matchOptionalTrailingSlash = (boolean) ReflectionUtils.getField(field, patternParser);
113-
assertThat(matchOptionalTrailingSlash).isTrue();
113+
assertThat(matchOptionalTrailingSlash).isFalse();
114114

115115
name = "webFluxContentTypeResolver";
116116
RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class);
@@ -124,18 +124,11 @@ public void requestMappingHandlerMapping() {
124124
@Test
125125
public void customPathMatchConfig() {
126126
ApplicationContext context = loadConfig(CustomPatchMatchConfig.class);
127-
final Field field = ReflectionUtils.findField(PathPatternParser.class, "matchOptionalTrailingSeparator");
128-
ReflectionUtils.makeAccessible(field);
129127

130128
String name = "requestMappingHandlerMapping";
131129
RequestMappingHandlerMapping mapping = context.getBean(name, RequestMappingHandlerMapping.class);
132130
assertThat(mapping).isNotNull();
133131

134-
PathPatternParser patternParser = mapping.getPathPatternParser();
135-
assertThat(patternParser).isNotNull();
136-
boolean matchOptionalTrailingSlash = (boolean) ReflectionUtils.getField(field, patternParser);
137-
assertThat(matchOptionalTrailingSlash).isFalse();
138-
139132
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
140133
assertThat(map.size()).isEqualTo(1);
141134
assertThat(map.keySet().iterator().next().getPatternsCondition().getPatterns())
@@ -323,7 +316,6 @@ static class CustomPatchMatchConfig extends WebFluxConfigurationSupport {
323316

324317
@Override
325318
public void configurePathMatching(PathMatchConfigurer configurer) {
326-
configurer.setUseTrailingSlashMatch(false);
327319
configurer.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
328320
}
329321

spring-webflux/src/test/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMappingTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -56,7 +56,6 @@ void handlerMappingJavaConfig() {
5656

5757
testUrl("/welcome.html", mainController, handlerMapping, "");
5858
testUrl("/welcome.x", otherController, handlerMapping, "welcome.x");
59-
testUrl("/welcome/", otherController, handlerMapping, "welcome");
6059
testUrl("/show.html", mainController, handlerMapping, "");
6160
testUrl("/bookseats.html", mainController, handlerMapping, "");
6261
}

spring-webflux/src/test/java/org/springframework/web/reactive/result/condition/PatternsRequestConditionTests.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -107,18 +107,22 @@ public void matchSortPatterns() {
107107
}
108108

109109
@Test
110+
@SuppressWarnings("deprecation")
110111
public void matchTrailingSlash() {
111112
MockServerWebExchange exchange = MockServerWebExchange.from(get("/foo/"));
112113

113-
PatternsRequestCondition condition = createPatternsCondition("/foo");
114+
PathPatternParser patternParser = new PathPatternParser();
115+
patternParser.setMatchOptionalTrailingSeparator(true);
116+
117+
PatternsRequestCondition condition = new PatternsRequestCondition(patternParser.parse("/foo"));
114118
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
115119

116120
assertThat(match).isNotNull();
117121
assertThat(match.getPatterns().iterator().next().getPatternString())
118122
.as("Should match by default")
119123
.isEqualTo("/foo");
120124

121-
condition = createPatternsCondition("/foo");
125+
condition = new PatternsRequestCondition(patternParser.parse("/foo"));
122126
match = condition.getMatchingCondition(exchange);
123127

124128
assertThat(match).isNotNull();

spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,6 @@ public void getHandlerEmptyPathMatch() {
119119
ServerWebExchange exchange = MockServerWebExchange.from(get(""));
120120
HandlerMethod hm = (HandlerMethod) this.handlerMapping.getHandler(exchange).block();
121121
assertThat(hm.getMethod()).isEqualTo(expected);
122-
123-
exchange = MockServerWebExchange.from(get("/"));
124-
hm = (HandlerMethod) this.handlerMapping.getHandler(exchange).block();
125-
assertThat(hm.getMethod()).isEqualTo(expected);
126122
}
127123

128124
@Test
@@ -157,7 +153,6 @@ public void getHandlerRequestMethodMatchFalsePositive() {
157153
@Test // SPR-8462
158154
public void getHandlerMediaTypeNotSupported() {
159155
testHttpMediaTypeNotSupportedException("/person/1");
160-
testHttpMediaTypeNotSupportedException("/person/1/");
161156
testHttpMediaTypeNotSupportedException("/person/1.json");
162157
}
163158

@@ -175,7 +170,6 @@ public void getHandlerTestInvalidContentType() {
175170
@Test // SPR-8462
176171
public void getHandlerTestMediaTypeNotAcceptable() {
177172
testMediaTypeNotAcceptable("/persons");
178-
testMediaTypeNotAcceptable("/persons/");
179173
}
180174

181175
@Test // SPR-12854

0 commit comments

Comments
 (0)