Remove Spring MVC suffixPattern and trailingSlash matching
See gh-34036
This commit is contained in:
@@ -370,16 +370,6 @@ public interface MockMvcWebTestClient {
|
||||
*/
|
||||
ControllerSpec patternParser(PathPatternParser parser);
|
||||
|
||||
/**
|
||||
* Whether to match trailing slashes.
|
||||
* <p>This is delegated to
|
||||
* {@link StandaloneMockMvcBuilder#setUseTrailingSlashPatternMatch(boolean)}.
|
||||
* @deprecated as of 6.0, see
|
||||
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
|
||||
*/
|
||||
@Deprecated(since = "6.0")
|
||||
ControllerSpec useTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch);
|
||||
|
||||
/**
|
||||
* Configure placeholder values to use.
|
||||
* <p>This is delegated to
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -152,13 +152,6 @@ class StandaloneMockMvcSpec extends AbstractMockMvcServerSpec<MockMvcWebTestClie
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public StandaloneMockMvcSpec useTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch) {
|
||||
this.mockMvcBuilder.setUseTrailingSlashPatternMatch(useTrailingSlashPatternMatch);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandaloneMockMvcSpec placeholderValue(String name, String value) {
|
||||
this.mockMvcBuilder.addPlaceholderValue(name, value);
|
||||
|
||||
@@ -130,10 +130,6 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
|
||||
@Nullable
|
||||
private PathPatternParser patternParser;
|
||||
|
||||
private boolean useSuffixPatternMatch = false;
|
||||
|
||||
private boolean useTrailingSlashPatternMatch = false;
|
||||
|
||||
@Nullable
|
||||
private Boolean removeSemicolonContent;
|
||||
|
||||
@@ -323,33 +319,6 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to use suffix pattern match (".*") when matching patterns to
|
||||
* requests. If enabled a method mapped to "/users" also matches to "/users.*".
|
||||
* <p>The default value is {@code false}.
|
||||
* @deprecated as of 5.2.4. See class-level note in
|
||||
* {@link RequestMappingHandlerMapping} on the deprecation of path extension
|
||||
* config options.
|
||||
*/
|
||||
@Deprecated
|
||||
public StandaloneMockMvcBuilder setUseSuffixPatternMatch(boolean useSuffixPatternMatch) {
|
||||
this.useSuffixPatternMatch = useSuffixPatternMatch;
|
||||
this.preferPathMatcher |= useSuffixPatternMatch;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to match to URLs irrespective of the presence of a trailing slash.
|
||||
* If enabled a method mapped to "/users" also matches to "/users/".
|
||||
* @deprecated as of 6.0, see
|
||||
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
|
||||
*/
|
||||
@Deprecated(since = "6.0")
|
||||
public StandaloneMockMvcBuilder setUseTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch) {
|
||||
this.useTrailingSlashPatternMatch = useTrailingSlashPatternMatch;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if ";" (semicolon) content should be stripped from the request URI. The value,
|
||||
* if provided, is in turn set on
|
||||
@@ -469,7 +438,6 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
|
||||
/** Using the MVC Java configuration as the starting point for the "standalone" setup. */
|
||||
private class StandaloneConfiguration extends WebMvcConfigurationSupport {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public RequestMappingHandlerMapping getHandlerMapping(
|
||||
FormattingConversionService mvcConversionService,
|
||||
ResourceUrlProvider mvcResourceUrlProvider) {
|
||||
@@ -478,7 +446,6 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
|
||||
handlerMapping.setEmbeddedValueResolver(new StaticStringValueResolver(placeholderValues));
|
||||
if (patternParser == null && preferPathMatcher) {
|
||||
handlerMapping.setPatternParser(null);
|
||||
handlerMapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
|
||||
if (removeSemicolonContent != null) {
|
||||
UrlPathHelper pathHelper = new UrlPathHelper();
|
||||
pathHelper.setRemoveSemicolonContent(removeSemicolonContent);
|
||||
@@ -488,7 +455,6 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
|
||||
else if (patternParser != null) {
|
||||
handlerMapping.setPatternParser(patternParser);
|
||||
}
|
||||
handlerMapping.setUseTrailingSlashMatch(useTrailingSlashPatternMatch);
|
||||
handlerMapping.setOrder(0);
|
||||
handlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
|
||||
return handlerMapping;
|
||||
|
||||
@@ -74,25 +74,6 @@ class StandaloneMockMvcBuilderTests {
|
||||
assertThat(((HandlerMethod) chain.getHandler()).getMethod().getName()).isEqualTo("handleWithPlaceholders");
|
||||
}
|
||||
|
||||
@Test // SPR-13637
|
||||
@SuppressWarnings("deprecation")
|
||||
void suffixPatternMatch() throws Exception {
|
||||
TestStandaloneMockMvcBuilder builder = new TestStandaloneMockMvcBuilder(new PersonController());
|
||||
builder.setUseSuffixPatternMatch(false);
|
||||
builder.build();
|
||||
|
||||
RequestMappingHandlerMapping hm = builder.wac.getBean(RequestMappingHandlerMapping.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/persons");
|
||||
HandlerExecutionChain chain = hm.getHandler(request);
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(((HandlerMethod) chain.getHandler()).getMethod().getName()).isEqualTo("persons");
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/persons.xml");
|
||||
chain = hm.getHandler(request);
|
||||
assertThat(chain).isNull();
|
||||
}
|
||||
|
||||
@Test // SPR-12553
|
||||
void applicationContextAttribute() {
|
||||
TestStandaloneMockMvcBuilder builder = new TestStandaloneMockMvcBuilder(new PlaceholderController());
|
||||
|
||||
@@ -409,21 +409,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
|
||||
Object source = context.extractSource(element);
|
||||
if (pathMatchingElement != null) {
|
||||
if (pathMatchingElement.hasAttribute("trailing-slash")) {
|
||||
boolean useTrailingSlashMatch = Boolean.parseBoolean(pathMatchingElement.getAttribute("trailing-slash"));
|
||||
handlerMappingDef.getPropertyValues().add("useTrailingSlashMatch", useTrailingSlashMatch);
|
||||
}
|
||||
boolean preferPathMatcher = false;
|
||||
if (pathMatchingElement.hasAttribute("suffix-pattern")) {
|
||||
boolean useSuffixPatternMatch = Boolean.parseBoolean(pathMatchingElement.getAttribute("suffix-pattern"));
|
||||
handlerMappingDef.getPropertyValues().add("useSuffixPatternMatch", useSuffixPatternMatch);
|
||||
preferPathMatcher |= useSuffixPatternMatch;
|
||||
}
|
||||
if (pathMatchingElement.hasAttribute("registered-suffixes-only")) {
|
||||
boolean useRegisteredSuffixPatternMatch = Boolean.parseBoolean(pathMatchingElement.getAttribute("registered-suffixes-only"));
|
||||
handlerMappingDef.getPropertyValues().add("useRegisteredSuffixPatternMatch", useRegisteredSuffixPatternMatch);
|
||||
preferPathMatcher |= useRegisteredSuffixPatternMatch;
|
||||
}
|
||||
|
||||
RuntimeBeanReference pathHelperRef = null;
|
||||
if (pathMatchingElement.hasAttribute("path-helper")) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -23,7 +23,6 @@ import java.util.function.Predicate;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
@@ -49,18 +48,9 @@ public class PathMatchConfigurer {
|
||||
@Nullable
|
||||
private PathPatternParser patternParser;
|
||||
|
||||
@Nullable
|
||||
private Boolean trailingSlashMatch;
|
||||
|
||||
@Nullable
|
||||
private Map<String, Predicate<Class<?>>> pathPrefixes;
|
||||
|
||||
@Nullable
|
||||
private Boolean suffixPatternMatch;
|
||||
|
||||
@Nullable
|
||||
private Boolean registeredSuffixPatternMatch;
|
||||
|
||||
@Nullable
|
||||
private UrlPathHelper urlPathHelper;
|
||||
|
||||
@@ -84,8 +74,6 @@ public class PathMatchConfigurer {
|
||||
* <p><strong>Note:</strong> This property is mutually exclusive with the
|
||||
* following other, {@code AntPathMatcher} related properties:
|
||||
* <ul>
|
||||
* <li>{@link #setUseSuffixPatternMatch(Boolean)}
|
||||
* <li>{@link #setUseRegisteredSuffixPatternMatch(Boolean)}
|
||||
* <li>{@link #setUrlPathHelper(UrlPathHelper)}
|
||||
* <li>{@link #setPathMatcher(PathMatcher)}
|
||||
* </ul>
|
||||
@@ -103,20 +91,6 @@ public class PathMatchConfigurer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to match to URLs irrespective of the presence of a trailing slash.
|
||||
* If enabled a method mapped to "/users" also matches to "/users/".
|
||||
* <p>The default was changed in 6.0 from {@code true} to {@code false} in
|
||||
* order to support the deprecation of the property.
|
||||
* @deprecated as of 6.0, see
|
||||
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
|
||||
*/
|
||||
@Deprecated(since = "6.0")
|
||||
public PathMatchConfigurer setUseTrailingSlashMatch(Boolean trailingSlashMatch) {
|
||||
this.trailingSlashMatch = trailingSlashMatch;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a path prefix to apply to matching controller methods.
|
||||
* <p>Prefixes are used to enrich the mappings of every {@code @RequestMapping}
|
||||
@@ -136,49 +110,6 @@ public class PathMatchConfigurer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to use suffix pattern match (".*") when matching patterns to
|
||||
* requests. If enabled a method mapped to "/users" also matches to "/users.*".
|
||||
* <p><strong>Note:</strong> This property is mutually exclusive with
|
||||
* {@link #setPatternParser(PathPatternParser)}. If set, it enables use of
|
||||
* String path matching, unless a {@code PathPatternParser} is also
|
||||
* explicitly set in which case this property is ignored.
|
||||
* <p>By default this is set to {@code false}.
|
||||
* @deprecated as of 5.2.4. See class-level note in
|
||||
* {@link RequestMappingHandlerMapping} on the deprecation of path extension
|
||||
* config options. As there is no replacement for this method, in 5.2.x it is
|
||||
* necessary to set it to {@code false}. In 5.3 the default changes to
|
||||
* {@code false} and use of this property becomes unnecessary.
|
||||
*/
|
||||
@Deprecated
|
||||
public PathMatchConfigurer setUseSuffixPatternMatch(@Nullable Boolean suffixPatternMatch) {
|
||||
this.suffixPatternMatch = suffixPatternMatch;
|
||||
this.preferPathMatcher |= (suffixPatternMatch != null && suffixPatternMatch);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether suffix pattern matching should work only against path extensions
|
||||
* explicitly registered when you
|
||||
* {@link WebMvcConfigurer#configureContentNegotiation configure content
|
||||
* negotiation}. This is generally recommended to reduce ambiguity and to
|
||||
* avoid issues such as when a "." appears in the path for other reasons.
|
||||
* <p><strong>Note:</strong> This property is mutually exclusive with
|
||||
* {@link #setPatternParser(PathPatternParser)}. If set, it enables use of
|
||||
* String path matching, unless a {@code PathPatternParser} is also
|
||||
* explicitly set in which case this property is ignored.
|
||||
* <p>By default this is set to "false".
|
||||
* @deprecated as of 5.2.4. See class-level note in
|
||||
* {@link RequestMappingHandlerMapping} on the deprecation of path extension
|
||||
* config options.
|
||||
*/
|
||||
@Deprecated
|
||||
public PathMatchConfigurer setUseRegisteredSuffixPatternMatch(@Nullable Boolean registeredSuffixPatternMatch) {
|
||||
this.registeredSuffixPatternMatch = registeredSuffixPatternMatch;
|
||||
this.preferPathMatcher |= (registeredSuffixPatternMatch != null && registeredSuffixPatternMatch);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UrlPathHelper to use to resolve the mapping path for the application.
|
||||
* <p><strong>Note:</strong> This property is mutually exclusive with
|
||||
@@ -232,39 +163,11 @@ public class PathMatchConfigurer {
|
||||
return this.patternParser;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public Boolean isUseTrailingSlashMatch() {
|
||||
return this.trailingSlashMatch;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Map<String, Predicate<Class<?>>> getPathPrefixes() {
|
||||
return this.pathPrefixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to use registered suffixes for pattern matching.
|
||||
* @deprecated as of 5.2.4, see deprecation note on
|
||||
* {@link #setUseRegisteredSuffixPatternMatch(Boolean)}.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public Boolean isUseRegisteredSuffixPatternMatch() {
|
||||
return this.registeredSuffixPatternMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to use registered suffixes for pattern matching.
|
||||
* @deprecated as of 5.2.4, see deprecation note on
|
||||
* {@link #setUseSuffixPatternMatch(Boolean)}.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public Boolean isUseSuffixPatternMatch() {
|
||||
return this.suffixPatternMatch;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UrlPathHelper getUrlPathHelper() {
|
||||
return this.urlPathHelper;
|
||||
|
||||
@@ -321,22 +321,6 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
initHandlerMapping(mapping, conversionService, resourceUrlProvider);
|
||||
|
||||
PathMatchConfigurer pathConfig = getPathMatchConfigurer();
|
||||
if (pathConfig.preferPathMatcher()) {
|
||||
Boolean useSuffixPatternMatch = pathConfig.isUseSuffixPatternMatch();
|
||||
if (useSuffixPatternMatch != null) {
|
||||
mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
|
||||
}
|
||||
Boolean useRegisteredSuffixPatternMatch = pathConfig.isUseRegisteredSuffixPatternMatch();
|
||||
if (useRegisteredSuffixPatternMatch != null) {
|
||||
mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
|
||||
}
|
||||
}
|
||||
|
||||
Boolean useTrailingSlashMatch = pathConfig.isUseTrailingSlashMatch();
|
||||
if (useTrailingSlashMatch != null) {
|
||||
mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
|
||||
}
|
||||
|
||||
if (pathConfig.getPathPrefixes() != null) {
|
||||
mapping.setPathPrefixes(pathConfig.getPathPrefixes());
|
||||
}
|
||||
@@ -520,6 +504,8 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
else if (pathConfig.getPatternParser() != null) {
|
||||
mapping.setPatternParser(pathConfig.getPatternParser());
|
||||
}
|
||||
// else: AbstractHandlerMapping defaults to PathPatternParser
|
||||
|
||||
mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
|
||||
mapping.setCorsConfigurations(getCorsConfigurations());
|
||||
}
|
||||
|
||||
@@ -60,12 +60,6 @@ public class PatternsRequestCondition extends AbstractRequestCondition<PatternsR
|
||||
|
||||
private final PathMatcher pathMatcher;
|
||||
|
||||
private final boolean useSuffixPatternMatch;
|
||||
|
||||
private final boolean useTrailingSlashMatch;
|
||||
|
||||
private final List<String> fileExtensions = new ArrayList<>();
|
||||
|
||||
|
||||
/**
|
||||
* Constructor with URL patterns which are prepended with "/" if necessary.
|
||||
@@ -73,85 +67,20 @@ public class PatternsRequestCondition extends AbstractRequestCondition<PatternsR
|
||||
* path {@code ""} mapping which matches all requests.
|
||||
*/
|
||||
public PatternsRequestCondition(String... patterns) {
|
||||
this(patterns, true, null);
|
||||
this(patterns, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #PatternsRequestCondition(String...)} with a
|
||||
* {@link PathMatcher} and flag for matching trailing slashes.
|
||||
* @since 5.3
|
||||
* Constructor with URL patterns which are prepended with "/" if necessary.
|
||||
* @param patterns 0 or more URL patterns; no patterns results in an empty
|
||||
* path {@code ""} mapping which matches all requests.
|
||||
* @since 7.0
|
||||
*/
|
||||
public PatternsRequestCondition(String[] patterns, boolean useTrailingSlashMatch,
|
||||
@Nullable PathMatcher pathMatcher) {
|
||||
|
||||
this(patterns, null, pathMatcher, useTrailingSlashMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #PatternsRequestCondition(String...)} with a
|
||||
* {@link UrlPathHelper} and a {@link PathMatcher}, and whether to match
|
||||
* trailing slashes.
|
||||
* <p>As of 5.3 the path is obtained through the static method
|
||||
* {@link UrlPathHelper#getResolvedLookupPath} and a {@code UrlPathHelper}
|
||||
* does not need to be passed in.
|
||||
* @since 5.2.4
|
||||
* @deprecated as of 5.3 in favor of
|
||||
* {@link #PatternsRequestCondition(String[], boolean, PathMatcher)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public PatternsRequestCondition(String[] patterns, @Nullable UrlPathHelper urlPathHelper,
|
||||
@Nullable PathMatcher pathMatcher, boolean useTrailingSlashMatch) {
|
||||
|
||||
this(patterns, urlPathHelper, pathMatcher, false, useTrailingSlashMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #PatternsRequestCondition(String...)} with a
|
||||
* {@link UrlPathHelper} and a {@link PathMatcher}, and flags for matching
|
||||
* with suffixes and trailing slashes.
|
||||
* <p>As of 5.3 the path is obtained through the static method
|
||||
* {@link UrlPathHelper#getResolvedLookupPath} and a {@code UrlPathHelper}
|
||||
* does not need to be passed in.
|
||||
* @deprecated as of 5.2.4. See class-level note in
|
||||
* {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping}
|
||||
* on the deprecation of path extension config options.
|
||||
*/
|
||||
@Deprecated
|
||||
public PatternsRequestCondition(String[] patterns, @Nullable UrlPathHelper urlPathHelper,
|
||||
@Nullable PathMatcher pathMatcher, boolean useSuffixPatternMatch, boolean useTrailingSlashMatch) {
|
||||
|
||||
this(patterns, urlPathHelper, pathMatcher, useSuffixPatternMatch, useTrailingSlashMatch, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #PatternsRequestCondition(String...)} with a
|
||||
* {@link UrlPathHelper} and a {@link PathMatcher}, and flags for matching
|
||||
* with suffixes and trailing slashes, along with specific extensions.
|
||||
* <p>As of 5.3 the path is obtained through the static method
|
||||
* {@link UrlPathHelper#getResolvedLookupPath} and a {@code UrlPathHelper}
|
||||
* does not need to be passed in.
|
||||
* @deprecated as of 5.2.4. See class-level note in
|
||||
* {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping}
|
||||
* on the deprecation of path extension config options.
|
||||
*/
|
||||
@Deprecated
|
||||
public PatternsRequestCondition(String[] patterns, @Nullable UrlPathHelper urlPathHelper,
|
||||
@Nullable PathMatcher pathMatcher, boolean useSuffixPatternMatch,
|
||||
boolean useTrailingSlashMatch, @Nullable List<String> fileExtensions) {
|
||||
public PatternsRequestCondition(
|
||||
String[] patterns, @Nullable UrlPathHelper urlPathHelper, @Nullable PathMatcher pathMatcher) {
|
||||
|
||||
this.patterns = initPatterns(patterns);
|
||||
this.pathMatcher = pathMatcher != null ? pathMatcher : new AntPathMatcher();
|
||||
this.useSuffixPatternMatch = useSuffixPatternMatch;
|
||||
this.useTrailingSlashMatch = useTrailingSlashMatch;
|
||||
|
||||
if (fileExtensions != null) {
|
||||
for (String fileExtension : fileExtensions) {
|
||||
if (fileExtension.charAt(0) != '.') {
|
||||
fileExtension = "." + fileExtension;
|
||||
}
|
||||
this.fileExtensions.add(fileExtension);
|
||||
}
|
||||
}
|
||||
this.pathMatcher = (pathMatcher != null ? pathMatcher : new AntPathMatcher());
|
||||
}
|
||||
|
||||
private static Set<String> initPatterns(String[] patterns) {
|
||||
@@ -183,9 +112,6 @@ public class PatternsRequestCondition extends AbstractRequestCondition<PatternsR
|
||||
private PatternsRequestCondition(Set<String> patterns, PatternsRequestCondition other) {
|
||||
this.patterns = patterns;
|
||||
this.pathMatcher = other.pathMatcher;
|
||||
this.useSuffixPatternMatch = other.useSuffixPatternMatch;
|
||||
this.useTrailingSlashMatch = other.useTrailingSlashMatch;
|
||||
this.fileExtensions.addAll(other.fileExtensions);
|
||||
}
|
||||
|
||||
|
||||
@@ -314,29 +240,9 @@ public class PatternsRequestCondition extends AbstractRequestCondition<PatternsR
|
||||
if (pattern.equals(lookupPath)) {
|
||||
return pattern;
|
||||
}
|
||||
if (this.useSuffixPatternMatch) {
|
||||
if (!this.fileExtensions.isEmpty() && lookupPath.indexOf('.') != -1) {
|
||||
for (String extension : this.fileExtensions) {
|
||||
if (this.pathMatcher.match(pattern + extension, lookupPath)) {
|
||||
return pattern + extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
boolean hasSuffix = pattern.indexOf('.') != -1;
|
||||
if (!hasSuffix && this.pathMatcher.match(pattern + ".*", lookupPath)) {
|
||||
return pattern + ".*";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.pathMatcher.match(pattern, lookupPath)) {
|
||||
return pattern;
|
||||
}
|
||||
if (this.useTrailingSlashMatch) {
|
||||
if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath)) {
|
||||
return pattern + "/";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc.method;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.servlet.ServletRequest;
|
||||
@@ -40,7 +39,6 @@ import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.RequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.RequestConditionHolder;
|
||||
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
@@ -702,7 +700,6 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public RequestMappingInfo build() {
|
||||
|
||||
PathPatternsRequestCondition pathPatternsCondition = null;
|
||||
@@ -718,10 +715,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
else {
|
||||
patternsCondition = (ObjectUtils.isEmpty(this.paths) ?
|
||||
EMPTY_PATTERNS :
|
||||
new PatternsRequestCondition(
|
||||
this.paths, null, this.options.pathMatcher,
|
||||
this.options.useSuffixPatternMatch(), this.options.useTrailingSlashMatch(),
|
||||
this.options.getFileExtensions()));
|
||||
new PatternsRequestCondition(this.paths, null, this.options.pathMatcher));
|
||||
}
|
||||
|
||||
ContentNegotiationManager manager = this.options.getContentNegotiationManager();
|
||||
@@ -783,7 +777,6 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Builder paths(String... paths) {
|
||||
PathPatternParser parser = this.options.getPatternParserToUse();
|
||||
|
||||
@@ -794,10 +787,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
else {
|
||||
this.patternsCondition = (ObjectUtils.isEmpty(paths) ?
|
||||
EMPTY_PATTERNS :
|
||||
new PatternsRequestCondition(
|
||||
paths, null, this.options.getPathMatcher(),
|
||||
this.options.useSuffixPatternMatch(), this.options.useTrailingSlashMatch(),
|
||||
this.options.getFileExtensions()));
|
||||
new PatternsRequestCondition(paths, null, this.options.getPathMatcher()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -876,7 +866,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
*/
|
||||
public static class BuilderConfiguration {
|
||||
|
||||
private static PathPatternParser defaultPatternParser = new PathPatternParser();
|
||||
private static final PathPatternParser defaultPatternParser = new PathPatternParser();
|
||||
|
||||
|
||||
@Nullable
|
||||
@@ -885,12 +875,6 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
@Nullable
|
||||
private PathMatcher pathMatcher;
|
||||
|
||||
private boolean trailingSlashMatch = false;
|
||||
|
||||
private boolean suffixPatternMatch = false;
|
||||
|
||||
private boolean registeredSuffixPatternMatch = false;
|
||||
|
||||
@Nullable
|
||||
private ContentNegotiationManager contentNegotiationManager;
|
||||
|
||||
@@ -900,7 +884,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
* {@link AbstractHandlerMapping#setPatternParser(PathPatternParser)}.
|
||||
* <p><strong>Note:</strong> This property is mutually exclusive with
|
||||
* {@link #setPathMatcher(PathMatcher)}.
|
||||
* <p>By default this is not set, but {@link RequestMappingInfo.Builder}
|
||||
* <p>By default, this is not set, but {@link RequestMappingInfo.Builder}
|
||||
* defaults to using {@link PathPatternParser} unless
|
||||
* {@link #setPathMatcher(PathMatcher)} is explicitly set.
|
||||
* @since 5.3
|
||||
@@ -944,7 +928,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
|
||||
/**
|
||||
* Set a custom PathMatcher to use for the PatternsRequestCondition.
|
||||
* <p>By default this is not set. You must set it explicitly if you want
|
||||
* <p>By default, this is not set. You must set it explicitly if you want
|
||||
* {@link PathMatcher} to be used, or otherwise {@link RequestMappingInfo}
|
||||
* defaults to using {@link PathPatternParser}.
|
||||
*/
|
||||
@@ -974,97 +958,9 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
return this.patternParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to apply trailing slash matching in PatternsRequestCondition.
|
||||
* <p>The default was changed in 6.0 from {@code true} to {@code false} in
|
||||
* order to support the deprecation of the property.
|
||||
* @deprecated as of 6.0, see
|
||||
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
|
||||
*/
|
||||
@Deprecated(since = "6.0")
|
||||
public void setTrailingSlashMatch(boolean trailingSlashMatch) {
|
||||
this.trailingSlashMatch = trailingSlashMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to apply trailing slash matching in PatternsRequestCondition.
|
||||
* @deprecated as of 6.0 together with {@link #setTrailingSlashMatch(boolean)}
|
||||
*/
|
||||
@Deprecated(since = "6.0")
|
||||
public boolean useTrailingSlashMatch() {
|
||||
return this.trailingSlashMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to apply suffix pattern matching in PatternsRequestCondition.
|
||||
* <p>By default this is set to 'false'.
|
||||
* @see #setRegisteredSuffixPatternMatch(boolean)
|
||||
* @deprecated as of 5.2.4. See deprecation note on
|
||||
* {@link RequestMappingHandlerMapping#setUseSuffixPatternMatch(boolean)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setSuffixPatternMatch(boolean suffixPatternMatch) {
|
||||
this.suffixPatternMatch = suffixPatternMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to apply suffix pattern matching in PatternsRequestCondition.
|
||||
* @deprecated as of 5.2.4. See deprecation note on
|
||||
* {@link RequestMappingHandlerMapping#setUseSuffixPatternMatch(boolean)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean useSuffixPatternMatch() {
|
||||
return this.suffixPatternMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether suffix pattern matching should be restricted to registered
|
||||
* file extensions only. Setting this property also sets
|
||||
* {@code suffixPatternMatch=true} and requires that a
|
||||
* {@link #setContentNegotiationManager} is also configured in order to
|
||||
* obtain the registered file extensions.
|
||||
* @deprecated as of 5.2.4. See class-level note in
|
||||
* {@link RequestMappingHandlerMapping} on the deprecation of path
|
||||
* extension config options.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setRegisteredSuffixPatternMatch(boolean registeredSuffixPatternMatch) {
|
||||
this.registeredSuffixPatternMatch = registeredSuffixPatternMatch;
|
||||
this.suffixPatternMatch = (registeredSuffixPatternMatch || this.suffixPatternMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether suffix pattern matching should be restricted to registered
|
||||
* file extensions only.
|
||||
* @deprecated as of 5.2.4. See class-level note in
|
||||
* {@link RequestMappingHandlerMapping} on the deprecation of path
|
||||
* extension config options.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean useRegisteredSuffixPatternMatch() {
|
||||
return this.registeredSuffixPatternMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the file extensions to use for suffix pattern matching. If
|
||||
* {@code registeredSuffixPatternMatch=true}, the extensions are obtained
|
||||
* from the configured {@code contentNegotiationManager}.
|
||||
* @deprecated as of 5.2.4. See class-level note in
|
||||
* {@link RequestMappingHandlerMapping} on the deprecation of path
|
||||
* extension config options.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public List<String> getFileExtensions() {
|
||||
if (useRegisteredSuffixPatternMatch() && this.contentNegotiationManager != null) {
|
||||
return this.contentNegotiationManager.getAllFileExtensions();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ContentNegotiationManager to use for the ProducesRequestCondition.
|
||||
* <p>By default this is not set.
|
||||
* <p>By default, this is not set.
|
||||
*/
|
||||
public void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) {
|
||||
this.contentNegotiationManager = contentNegotiationManager;
|
||||
|
||||
@@ -59,22 +59,12 @@ import org.springframework.web.servlet.mvc.condition.RequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
/**
|
||||
* Creates {@link RequestMappingInfo} instances from type-level and method-level
|
||||
* {@link RequestMapping @RequestMapping} and {@link HttpExchange @HttpExchange}
|
||||
* annotations in {@link Controller @Controller} classes.
|
||||
*
|
||||
* <p><strong>Deprecation Note:</strong></p> In 5.2.4,
|
||||
* {@link #setUseSuffixPatternMatch(boolean) useSuffixPatternMatch} and
|
||||
* {@link #setUseRegisteredSuffixPatternMatch(boolean) useRegisteredSuffixPatternMatch}
|
||||
* were deprecated in order to discourage use of path extensions for request
|
||||
* mapping and for content negotiation (with similar deprecations in
|
||||
* {@link org.springframework.web.accept.ContentNegotiationManagerFactoryBean
|
||||
* ContentNegotiationManagerFactoryBean}). For further context, please read issue
|
||||
* <a href="https://github.com/spring-projects/spring-framework/issues/24179">#24179</a>.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Sam Brannen
|
||||
@@ -89,14 +79,6 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||
private static final RequestMethod[] EMPTY_REQUEST_METHOD_ARRAY = new RequestMethod[0];
|
||||
|
||||
|
||||
private boolean defaultPatternParser = true;
|
||||
|
||||
private boolean useSuffixPatternMatch = false;
|
||||
|
||||
private boolean useRegisteredSuffixPatternMatch = false;
|
||||
|
||||
private boolean useTrailingSlashMatch = false;
|
||||
|
||||
private Map<String, Predicate<Class<?>>> pathPrefixes = Collections.emptyMap();
|
||||
|
||||
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
|
||||
@@ -107,65 +89,6 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||
private RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();
|
||||
|
||||
|
||||
@Override
|
||||
public void setPatternParser(@Nullable PathPatternParser patternParser) {
|
||||
if (patternParser != null) {
|
||||
this.defaultPatternParser = false;
|
||||
}
|
||||
super.setPatternParser(patternParser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to use suffix pattern match (".*") when matching patterns to
|
||||
* requests. If enabled a method mapped to "/users" also matches to "/users.*".
|
||||
* <p>By default value this is set to {@code false}.
|
||||
* <p>Also see {@link #setUseRegisteredSuffixPatternMatch(boolean)} for
|
||||
* more fine-grained control over specific suffixes to allow.
|
||||
* <p><strong>Note:</strong> This property is ignored when
|
||||
* {@link #setPatternParser(PathPatternParser)} is configured.
|
||||
* @deprecated as of 5.2.4. See class level note on the deprecation of
|
||||
* path extension config options. As there is no replacement for this method,
|
||||
* in 5.2.x it is necessary to set it to {@code false}. In 5.3 the default
|
||||
* changes to {@code false} and use of this property becomes unnecessary.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUseSuffixPatternMatch(boolean useSuffixPatternMatch) {
|
||||
this.useSuffixPatternMatch = useSuffixPatternMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether suffix pattern matching should work only against path extensions
|
||||
* explicitly registered with the {@link ContentNegotiationManager}. This
|
||||
* is generally recommended to reduce ambiguity and to avoid issues such as
|
||||
* when a "." appears in the path for other reasons.
|
||||
* <p>By default this is set to "false".
|
||||
* <p><strong>Note:</strong> This property is ignored when
|
||||
* {@link #setPatternParser(PathPatternParser)} is configured.
|
||||
* @deprecated as of 5.2.4. See class level note on the deprecation of
|
||||
* path extension config options.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUseRegisteredSuffixPatternMatch(boolean useRegisteredSuffixPatternMatch) {
|
||||
this.useRegisteredSuffixPatternMatch = useRegisteredSuffixPatternMatch;
|
||||
this.useSuffixPatternMatch = (useRegisteredSuffixPatternMatch || this.useSuffixPatternMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to match to URLs irrespective of the presence of a trailing slash.
|
||||
* If enabled a method mapped to "/users" also matches to "/users/".
|
||||
* <p>The default was changed in 6.0 from {@code true} to {@code false} in
|
||||
* order to support the deprecation of the property.
|
||||
* @deprecated as of 6.0, see
|
||||
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
|
||||
*/
|
||||
@Deprecated(since = "6.0")
|
||||
public void setUseTrailingSlashMatch(boolean useTrailingSlashMatch) {
|
||||
this.useTrailingSlashMatch = useTrailingSlashMatch;
|
||||
if (getPatternParser() != null) {
|
||||
getPatternParser().setMatchOptionalTrailingSeparator(useTrailingSlashMatch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure path prefixes to apply to controller methods.
|
||||
* <p>Prefixes are used to enrich the mappings of every {@code @RequestMapping}
|
||||
@@ -216,23 +139,12 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||
@SuppressWarnings("deprecation")
|
||||
public void afterPropertiesSet() {
|
||||
this.config = new RequestMappingInfo.BuilderConfiguration();
|
||||
this.config.setTrailingSlashMatch(useTrailingSlashMatch());
|
||||
this.config.setContentNegotiationManager(getContentNegotiationManager());
|
||||
|
||||
if (getPatternParser() != null && this.defaultPatternParser &&
|
||||
(this.useSuffixPatternMatch || this.useRegisteredSuffixPatternMatch)) {
|
||||
|
||||
setPatternParser(null);
|
||||
}
|
||||
|
||||
if (getPatternParser() != null) {
|
||||
this.config.setPatternParser(getPatternParser());
|
||||
Assert.isTrue(!this.useSuffixPatternMatch && !this.useRegisteredSuffixPatternMatch,
|
||||
"Suffix pattern matching not supported with PathPatternParser.");
|
||||
}
|
||||
else {
|
||||
this.config.setSuffixPatternMatch(useSuffixPatternMatch());
|
||||
this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
|
||||
this.config.setPathMatcher(getPathMatcher());
|
||||
}
|
||||
|
||||
@@ -240,45 +152,6 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether to use registered suffixes for pattern matching.
|
||||
* @deprecated as of 5.2.4. See deprecation notice on
|
||||
* {@link #setUseSuffixPatternMatch(boolean)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean useSuffixPatternMatch() {
|
||||
return this.useSuffixPatternMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to use registered suffixes for pattern matching.
|
||||
* @deprecated as of 5.2.4. See deprecation notice on
|
||||
* {@link #setUseRegisteredSuffixPatternMatch(boolean)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean useRegisteredSuffixPatternMatch() {
|
||||
return this.useRegisteredSuffixPatternMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to match to URLs irrespective of the presence of a trailing slash.
|
||||
*/
|
||||
public boolean useTrailingSlashMatch() {
|
||||
return this.useTrailingSlashMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the file extensions to use for suffix pattern matching.
|
||||
* @deprecated as of 5.2.4. See class-level note on the deprecation of path
|
||||
* extension config options.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
@SuppressWarnings("deprecation")
|
||||
public List<String> getFileExtensions() {
|
||||
return this.config.getFileExtensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a {@link RequestMappingInfo.BuilderConfiguration} that reflects
|
||||
* the internal configuration of this {@code HandlerMapping} and can be used
|
||||
|
||||
@@ -31,51 +31,6 @@
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="suffix-pattern" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Whether to use suffix pattern match (".*") when matching patterns to requests. If enabled
|
||||
a method mapped to "/users" also matches to "/users.*".
|
||||
|
||||
In 5.2.4, suffix pattern matching was deprecated in order to discourage use of path
|
||||
extensions for request mapping and for content negotiation (see deprecation notes on
|
||||
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping and on
|
||||
org.springframework.web.accept.ContentNegotiationManagerFactoryBean and
|
||||
also see https://github.com/spring-projects/spring-framework/issues/24179.
|
||||
|
||||
The default value is true but in 5.3 it changes to false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="trailing-slash" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Whether to match to URLs irrespective of the presence of a trailing slash.
|
||||
If enabled a method mapped to "/users" also matches to "/users/".
|
||||
|
||||
The default was changed in 6.0 from true to false in order to support the
|
||||
deprecation of the property.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="registered-suffixes-only" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Whether suffix pattern matching should work only against path extensions
|
||||
explicitly registered when you configure content negotiation.
|
||||
This is generally recommended to reduce ambiguity and to
|
||||
avoid issues such as when a "." appears in the path for other reasons.
|
||||
|
||||
In 5.2.4, suffix pattern matching was deprecated in order to discourage use of path
|
||||
extensions for request mapping and for content negotiation (see deprecation notes on
|
||||
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping and on
|
||||
org.springframework.web.accept.ContentNegotiationManagerFactoryBean and
|
||||
also see https://github.com/spring-projects/spring-framework/issues/24179.
|
||||
|
||||
The default value is false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="path-helper" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
@@ -79,19 +79,13 @@ class AnnotationDrivenBeanDefinitionParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void testPathMatchingConfiguration() {
|
||||
loadBeanDefinitions("mvc-config-path-matching.xml");
|
||||
RequestMappingHandlerMapping hm = this.appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
assertThat(hm).isNotNull();
|
||||
assertThat(hm.useSuffixPatternMatch()).isTrue();
|
||||
assertThat(hm.useTrailingSlashMatch()).isFalse();
|
||||
assertThat(hm.useRegisteredSuffixPatternMatch()).isTrue();
|
||||
assertThat(hm.getUrlPathHelper()).isInstanceOf(TestPathHelper.class);
|
||||
assertThat(hm.getPathMatcher()).isInstanceOf(TestPathMatcher.class);
|
||||
assertThat(hm.getPatternParser()).isNull();
|
||||
List<String> fileExtensions = hm.getContentNegotiationManager().getAllFileExtensions();
|
||||
assertThat(fileExtensions).containsExactly("xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -240,10 +240,7 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void configurePathMatch(PathMatchConfigurer configurer) {
|
||||
configurer.setUseRegisteredSuffixPatternMatch(true)
|
||||
.setUseTrailingSlashMatch(false)
|
||||
.setUrlPathHelper(pathHelper)
|
||||
.setPathMatcher(pathMatcher);
|
||||
configurer.setUrlPathHelper(pathHelper).setPathMatcher(pathMatcher);
|
||||
}
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
@@ -272,9 +269,6 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
webMvcConfig.mvcResourceUrlProvider());
|
||||
|
||||
assertThat(annotationsMapping).isNotNull();
|
||||
assertThat(annotationsMapping.useRegisteredSuffixPatternMatch()).isTrue();
|
||||
assertThat(annotationsMapping.useSuffixPatternMatch()).isTrue();
|
||||
assertThat(annotationsMapping.useTrailingSlashMatch()).isFalse();
|
||||
configAssertion.accept(annotationsMapping.getUrlPathHelper(), annotationsMapping.getPathMatcher());
|
||||
|
||||
SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping) webMvcConfig.viewControllerHandlerMapping(
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc.condition;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -111,88 +109,6 @@ class PatternsRequestConditionTests {
|
||||
assertThat(match).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
void matchSuffixPattern() {
|
||||
MockHttpServletRequest request = initRequest("/foo.html");
|
||||
|
||||
boolean useSuffixPatternMatch = true;
|
||||
PatternsRequestCondition condition =
|
||||
new PatternsRequestCondition(new String[] {"/{foo}"}, null, null, useSuffixPatternMatch, true);
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatterns()).containsExactly("/{foo}.*");
|
||||
|
||||
useSuffixPatternMatch = false;
|
||||
condition = new PatternsRequestCondition(
|
||||
new String[] {"/{foo}"}, null, null, useSuffixPatternMatch, false);
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatterns()).containsExactly("/{foo}");
|
||||
}
|
||||
|
||||
@Test // SPR-8410
|
||||
@SuppressWarnings("deprecation")
|
||||
void matchSuffixPatternUsingFileExtensions() {
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition(
|
||||
new String[] {"/jobs/{jobName}"}, null, null, true, false, Collections.singletonList("json"));
|
||||
|
||||
MockHttpServletRequest request = initRequest("/jobs/my.job");
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatterns()).containsExactly("/jobs/{jobName}");
|
||||
|
||||
request = initRequest("/jobs/my.job.json");
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatterns()).containsExactly("/jobs/{jobName}.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
void matchSuffixPatternUsingFileExtensions2() {
|
||||
PatternsRequestCondition condition1 = new PatternsRequestCondition(
|
||||
new String[] {"/prefix"}, null, null, true, false, Collections.singletonList("json"));
|
||||
|
||||
PatternsRequestCondition condition2 = new PatternsRequestCondition(
|
||||
new String[] {"/suffix"}, null, null, true, false, null);
|
||||
|
||||
PatternsRequestCondition combined = condition1.combine(condition2);
|
||||
|
||||
MockHttpServletRequest request = initRequest("/prefix/suffix.json");
|
||||
PatternsRequestCondition match = combined.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchTrailingSlash() {
|
||||
MockHttpServletRequest request = initRequest("/foo/");
|
||||
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatterns()).containsExactly("/foo/");
|
||||
|
||||
condition = new PatternsRequestCondition(new String[] {"/foo"}, true, null);
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatterns()).first(STRING)
|
||||
.as("Trailing slash should be insensitive to useSuffixPatternMatch settings (SPR-6164, SPR-5636)")
|
||||
.isEqualTo("/foo/");
|
||||
|
||||
condition = new PatternsRequestCondition(new String[] {"/foo"}, false, null);
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchPatternContainsExtension() {
|
||||
MockHttpServletRequest request = initRequest("/foo.html");
|
||||
@@ -203,11 +119,7 @@ class PatternsRequestConditionTests {
|
||||
|
||||
@Test // gh-22543
|
||||
void matchWithEmptyPatterns() {
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition();
|
||||
assertThat(condition.getMatchingCondition(initRequest(""))).isNotNull();
|
||||
assertThat(condition.getMatchingCondition(initRequest("/anything"))).isNull();
|
||||
|
||||
condition = condition.combine(new PatternsRequestCondition());
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition().combine(new PatternsRequestCondition());
|
||||
assertThat(condition.getMatchingCondition(initRequest(""))).isNotNull();
|
||||
assertThat(condition.getMatchingCondition(initRequest("/anything"))).isNull();
|
||||
}
|
||||
|
||||
@@ -616,15 +616,12 @@ class RequestMappingInfoHandlerMappingTests {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private RequestMappingInfo.BuilderConfiguration getBuilderConfig() {
|
||||
RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();
|
||||
if (getPatternParser() != null) {
|
||||
config.setPatternParser(getPatternParser());
|
||||
}
|
||||
else {
|
||||
config.setSuffixPatternMatch(true);
|
||||
config.setRegisteredSuffixPatternMatch(true);
|
||||
config.setPathMatcher(getPathMatcher());
|
||||
}
|
||||
return config;
|
||||
|
||||
@@ -23,8 +23,6 @@ import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -35,7 +33,6 @@ import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
@@ -102,74 +99,6 @@ class RequestMappingHandlerMappingTests {
|
||||
assertThat(mapping.getBuilderConfiguration()).isNotNull().isNotSameAs(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
void useRegisteredSuffixPatternMatch() {
|
||||
RequestMappingHandlerMapping mapping = createMapping();
|
||||
|
||||
Map<String, MediaType> fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
|
||||
org.springframework.web.accept.PathExtensionContentNegotiationStrategy strategy =
|
||||
new org.springframework.web.accept.PathExtensionContentNegotiationStrategy(fileExtensions);
|
||||
ContentNegotiationManager manager = new ContentNegotiationManager(strategy);
|
||||
|
||||
mapping.setContentNegotiationManager(manager);
|
||||
mapping.setUseRegisteredSuffixPatternMatch(true);
|
||||
mapping.afterPropertiesSet();
|
||||
|
||||
assertThat(mapping.useSuffixPatternMatch()).isTrue();
|
||||
assertThat(mapping.useRegisteredSuffixPatternMatch()).isTrue();
|
||||
assertThat(mapping.getFileExtensions()).isEqualTo(Collections.singletonList("json"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
void useRegisteredSuffixPatternMatchInitialization() {
|
||||
Map<String, MediaType> fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
|
||||
org.springframework.web.accept.PathExtensionContentNegotiationStrategy strategy =
|
||||
new org.springframework.web.accept.PathExtensionContentNegotiationStrategy(fileExtensions);
|
||||
ContentNegotiationManager manager = new ContentNegotiationManager(strategy);
|
||||
|
||||
final Set<String> extensions = new HashSet<>();
|
||||
|
||||
RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping() {
|
||||
@Override
|
||||
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
extensions.addAll(getFileExtensions());
|
||||
return super.getMappingForMethod(method, handlerType);
|
||||
}
|
||||
};
|
||||
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.registerSingleton("testController", ComposedAnnotationController.class);
|
||||
wac.refresh();
|
||||
|
||||
mapping.setContentNegotiationManager(manager);
|
||||
mapping.setUseRegisteredSuffixPatternMatch(true);
|
||||
mapping.setApplicationContext(wac);
|
||||
mapping.afterPropertiesSet();
|
||||
|
||||
assertThat(extensions).containsOnly("json");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
void suffixPatternMatchSettings() {
|
||||
RequestMappingHandlerMapping mapping = createMapping();
|
||||
|
||||
assertThat(mapping.useSuffixPatternMatch()).isFalse();
|
||||
assertThat(mapping.useRegisteredSuffixPatternMatch()).isFalse();
|
||||
|
||||
mapping.setUseRegisteredSuffixPatternMatch(false);
|
||||
assertThat(mapping.useSuffixPatternMatch())
|
||||
.as("'false' registeredSuffixPatternMatch shouldn't impact suffixPatternMatch")
|
||||
.isFalse();
|
||||
|
||||
mapping.setUseRegisteredSuffixPatternMatch(true);
|
||||
assertThat(mapping.useSuffixPatternMatch())
|
||||
.as("'true' registeredSuffixPatternMatch should enable suffixPatternMatch")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void resolveEmbeddedValuesInPatterns(RequestMappingHandlerMapping mapping) {
|
||||
mapping.setEmbeddedValueResolver(value -> "/${pattern}/bar".equals(value) ? "/foo/bar" : value);
|
||||
|
||||
@@ -178,15 +178,7 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void emptyValueMapping(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(ControllerWithEmptyValueMapping.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
// UrlPathHelper returns "/" for "",
|
||||
// so either the mapping has to be "/" or trailingSlashMatch must be on
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useTrailingSlashMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
});
|
||||
initDispatcherServlet(ControllerWithEmptyValueMapping.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
request.setContextPath("/foo");
|
||||
@@ -207,15 +199,7 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void errorThrownFromHandlerMethod(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(ControllerWithErrorThrown.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
// UrlPathHelper returns "/" for "",
|
||||
// so either the mapping has to be "/" or trailingSlashMatch must be on
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useTrailingSlashMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
});
|
||||
initDispatcherServlet(ControllerWithErrorThrown.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
request.setContextPath("/foo");
|
||||
@@ -514,13 +498,7 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void adaptedHandleMethods(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(MyAdaptedController.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
});
|
||||
initDispatcherServlet(MyAdaptedController.class, usePathPatterns);
|
||||
doTestAdaptedHandleMethods(usePathPatterns);
|
||||
}
|
||||
|
||||
@@ -560,12 +538,6 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
|
||||
if (!usePathPatterns) {
|
||||
// This depends on suffix pattern matching and has different outcomes otherwise,
|
||||
// for example, 404 vs another method matching, depending on the test case.
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-name1-2");
|
||||
}
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/myPath4.do");
|
||||
request.addParameter("param1", "value1");
|
||||
request.addParameter("param2", "2");
|
||||
@@ -787,13 +759,7 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void relativePathDispatchingController(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(MyRelativePathDispatchingController.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
});
|
||||
initDispatcherServlet(MyRelativePathDispatchingController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -809,22 +775,11 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getContentAsString()).isEqualTo("myLangView");
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/myApp/surprise.do");
|
||||
response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getContentAsString()).isEqualTo(!usePathPatterns ? "mySurpriseView" : "myView");
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void relativeMethodPathDispatchingController(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(MyRelativeMethodPathDispatchingController.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
});
|
||||
initDispatcherServlet(MyRelativeMethodPathDispatchingController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -845,15 +800,7 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
|
||||
if (!usePathPatterns) {
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
assertThat(response.getContentAsString()).isEqualTo("mySurpriseView");
|
||||
}
|
||||
else {
|
||||
assertThat(response.getStatus())
|
||||
.as("Suffixes pattern matching should not work with PathPattern's")
|
||||
.isEqualTo(404);
|
||||
}
|
||||
assertThat(response.getStatus()).as("Suffixes pattern matching is not supported").isEqualTo(404);
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
@@ -1776,108 +1723,6 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
assertThat(response.getContentLength()).as("Expected an empty content").isEqualTo(0);
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
@SuppressWarnings("deprecation")
|
||||
void responseBodyAsHtml(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(TextRestController.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
// `useSuffixPatternMatch` is not allowed with PathPattern's
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
|
||||
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
|
||||
factoryBean.setFavorPathExtension(true);
|
||||
factoryBean.afterPropertiesSet();
|
||||
|
||||
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
|
||||
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
|
||||
wac.registerBeanDefinition("handlerAdapter", adapterDef);
|
||||
});
|
||||
|
||||
byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/a1.html");
|
||||
request.setContent(content);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
getServlet().service(request, response);
|
||||
|
||||
if (!usePathPatterns) {
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
assertThat(response.getContentType()).isEqualTo("text/html;charset=ISO-8859-1");
|
||||
assertThat(response.getHeader("Content-Disposition")).isEqualTo("inline;filename=f.txt");
|
||||
assertThat(response.getContentAsByteArray()).isEqualTo(content);
|
||||
}
|
||||
else {
|
||||
assertThat(response.getStatus())
|
||||
.as("Suffixes pattern matching should not work with PathPattern's")
|
||||
.isEqualTo(404);
|
||||
}
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
@SuppressWarnings("deprecation")
|
||||
void responseBodyAsHtmlWithSuffixPresent(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(TextRestController.class, usePathPatterns, wac -> {
|
||||
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
|
||||
factoryBean.setFavorPathExtension(true);
|
||||
factoryBean.afterPropertiesSet();
|
||||
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
|
||||
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
|
||||
wac.registerBeanDefinition("handlerAdapter", adapterDef);
|
||||
});
|
||||
|
||||
byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/a2.html");
|
||||
request.setContent(content);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
getServlet().service(request, response);
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
assertThat(response.getContentType()).isEqualTo("text/html;charset=ISO-8859-1");
|
||||
assertThat(response.getHeader("Content-Disposition")).isNull();
|
||||
assertThat(response.getContentAsByteArray()).isEqualTo(content);
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void responseBodyAsHtmlWithProducesCondition(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(TextRestController.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
|
||||
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
|
||||
factoryBean.afterPropertiesSet();
|
||||
|
||||
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
|
||||
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
|
||||
wac.registerBeanDefinition("handlerAdapter", adapterDef);
|
||||
});
|
||||
|
||||
byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/a3.html");
|
||||
request.setContent(content);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
getServlet().service(request, response);
|
||||
|
||||
if (!usePathPatterns) {
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
assertThat(response.getContentType()).isEqualTo("text/html;charset=ISO-8859-1");
|
||||
assertThat(response.getHeader("Content-Disposition")).isNull();
|
||||
assertThat(response.getContentAsByteArray()).isEqualTo(content);
|
||||
}
|
||||
else {
|
||||
assertThat(response.getStatus())
|
||||
.as("Suffixes pattern matching should not work with PathPattern's")
|
||||
.isEqualTo(404);
|
||||
}
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void responseBodyAsTextWithCssExtension(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(TextRestController.class, usePathPatterns, wac -> {
|
||||
@@ -3052,7 +2897,6 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
|
||||
static class TestViewResolver implements ViewResolver {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public View resolveViewName(final String viewName, Locale locale) throws Exception {
|
||||
return (model, request, response) -> {
|
||||
@@ -4021,16 +3865,6 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||
return body;
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/a2.html", method = RequestMethod.GET)
|
||||
public String a2(@RequestBody String body) {
|
||||
return body;
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/a3", method = RequestMethod.GET, produces = "text/html")
|
||||
public String a3(@RequestBody String body) throws IOException {
|
||||
return body;
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/a4", method = RequestMethod.GET)
|
||||
public String a4(@RequestBody String body) {
|
||||
return body;
|
||||
|
||||
@@ -173,7 +173,6 @@ class UriTemplateServletAnnotationControllerHandlerMethodTests extends AbstractS
|
||||
initDispatcherServlet(SimpleUriTemplateController.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
mappingDef.getPropertyValues().add("removeSemicolonContent", "false");
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
@@ -182,8 +181,7 @@ class UriTemplateServletAnnotationControllerHandlerMethodTests extends AbstractS
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42;jsessionid=c0o7fszeb1;q=24.xml");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getContentAsString())
|
||||
.isEqualTo(!usePathPatterns ? "test-42-24" : "test-42-24.xml");
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-42-24.xml");
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
@@ -320,18 +318,12 @@ class UriTemplateServletAnnotationControllerHandlerMethodTests extends AbstractS
|
||||
|
||||
@PathPatternsParameterizedTest // gh-13187
|
||||
void variableNamesWithUrlExtension(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(VariableNamesController.class, usePathPatterns, wac -> {
|
||||
if (!usePathPatterns) {
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}
|
||||
});
|
||||
initDispatcherServlet(VariableNamesController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo.json");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getContentAsString()).isEqualTo(!usePathPatterns ? "foo-foo" : "foo-foo.json");
|
||||
assertThat(response.getContentAsString()).isEqualTo("foo-foo.json");
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest // gh-11643
|
||||
@@ -683,13 +675,4 @@ class UriTemplateServletAnnotationControllerHandlerMethodTests extends AbstractS
|
||||
}
|
||||
}
|
||||
|
||||
// @Disabled("ControllerClassNameHandlerMapping")
|
||||
// void controllerClassName() throws Exception {
|
||||
|
||||
// @Disabled("useDefaultSuffixPattern property not supported")
|
||||
// void doubles() throws Exception {
|
||||
|
||||
// @Disabled("useDefaultSuffixPattern property not supported")
|
||||
// void noDefaultSuffixPattern() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@@ -149,10 +149,8 @@ class ResourceHttpRequestHandlerTests {
|
||||
}
|
||||
|
||||
@Test // SPR-14577
|
||||
@SuppressWarnings("deprecation")
|
||||
void getMediaTypeWithFavorPathExtensionOff() throws Exception {
|
||||
ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean();
|
||||
factory.setFavorPathExtension(false);
|
||||
factory.afterPropertiesSet();
|
||||
ContentNegotiationManager manager = factory.getObject();
|
||||
|
||||
|
||||
@@ -6,12 +6,7 @@
|
||||
http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
|
||||
<mvc:path-matching
|
||||
suffix-pattern="true"
|
||||
trailing-slash="false"
|
||||
registered-suffixes-only="true"
|
||||
path-helper="pathHelper"
|
||||
path-matcher="pathMatcher" />
|
||||
<mvc:path-matching path-helper="pathHelper" path-matcher="pathMatcher" />
|
||||
</mvc:annotation-driven>
|
||||
|
||||
<bean id="pathMatcher" class="org.springframework.web.servlet.config.TestPathMatcher" />
|
||||
|
||||
Reference in New Issue
Block a user