Support for parsed PathPatterns in Spring MVC
See gh-24945
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,9 +16,9 @@
|
||||
|
||||
package org.springframework.web.servlet.config.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -34,16 +34,20 @@ import org.springframework.util.PathMatcher;
|
||||
import org.springframework.validation.DefaultMessageCodesResolver;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -82,15 +86,16 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
@Captor
|
||||
private ArgumentCaptor<List<HandlerExceptionResolver>> exceptionResolvers;
|
||||
|
||||
private final DelegatingWebMvcConfiguration delegatingConfig = new DelegatingWebMvcConfiguration();
|
||||
private final DelegatingWebMvcConfiguration webMvcConfig = new DelegatingWebMvcConfiguration();
|
||||
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerAdapter() throws Exception {
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
RequestMappingHandlerAdapter adapter = this.delegatingConfig.requestMappingHandlerAdapter(
|
||||
this.delegatingConfig.mvcContentNegotiationManager(), this.delegatingConfig.mvcConversionService(),
|
||||
this.delegatingConfig.mvcValidator());
|
||||
public void requestMappingHandlerAdapter() {
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
RequestMappingHandlerAdapter adapter = this.webMvcConfig.requestMappingHandlerAdapter(
|
||||
this.webMvcConfig.mvcContentNegotiationManager(),
|
||||
this.webMvcConfig.mvcConversionService(),
|
||||
this.webMvcConfig.mvcValidator());
|
||||
|
||||
ConfigurableWebBindingInitializer initializer =
|
||||
(ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer();
|
||||
@@ -114,10 +119,9 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void configureMessageConverters() {
|
||||
final HttpMessageConverter<?> customConverter = mock(HttpMessageConverter.class);
|
||||
final StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
|
||||
List<WebMvcConfigurer> configurers = new ArrayList<>();
|
||||
configurers.add(new WebMvcConfigurer() {
|
||||
HttpMessageConverter<?> customConverter = mock(HttpMessageConverter.class);
|
||||
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
|
||||
WebMvcConfigurer configurer = new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.add(stringConverter);
|
||||
@@ -127,13 +131,15 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.add(0, customConverter);
|
||||
}
|
||||
});
|
||||
delegatingConfig.setConfigurers(configurers);
|
||||
};
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(configurer));
|
||||
|
||||
RequestMappingHandlerAdapter adapter = delegatingConfig.requestMappingHandlerAdapter(
|
||||
this.delegatingConfig.mvcContentNegotiationManager(), this.delegatingConfig.mvcConversionService(),
|
||||
this.delegatingConfig.mvcValidator());
|
||||
assertThat(adapter.getMessageConverters().size()).as("Only one custom converter should be registered").isEqualTo(2);
|
||||
RequestMappingHandlerAdapter adapter = webMvcConfig.requestMappingHandlerAdapter(
|
||||
this.webMvcConfig.mvcContentNegotiationManager(),
|
||||
this.webMvcConfig.mvcConversionService(),
|
||||
this.webMvcConfig.mvcValidator());
|
||||
|
||||
assertThat(adapter.getMessageConverters().size()).as("One custom converter expected").isEqualTo(2);
|
||||
assertThat(adapter.getMessageConverters().get(0)).isSameAs(customConverter);
|
||||
assertThat(adapter.getMessageConverters().get(1)).isSameAs(stringConverter);
|
||||
}
|
||||
@@ -142,8 +148,8 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
public void getCustomValidator() {
|
||||
given(webMvcConfigurer.getValidator()).willReturn(new LocalValidatorFactoryBean());
|
||||
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
delegatingConfig.mvcValidator();
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
webMvcConfig.mvcValidator();
|
||||
|
||||
verify(webMvcConfigurer).getValidator();
|
||||
}
|
||||
@@ -152,16 +158,16 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
public void getCustomMessageCodesResolver() {
|
||||
given(webMvcConfigurer.getMessageCodesResolver()).willReturn(new DefaultMessageCodesResolver());
|
||||
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
delegatingConfig.getMessageCodesResolver();
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
webMvcConfig.getMessageCodesResolver();
|
||||
|
||||
verify(webMvcConfigurer).getMessageCodesResolver();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlerExceptionResolver() throws Exception {
|
||||
delegatingConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
delegatingConfig.handlerExceptionResolver(delegatingConfig.mvcContentNegotiationManager());
|
||||
public void handlerExceptionResolver() {
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
webMvcConfig.handlerExceptionResolver(webMvcConfig.mvcContentNegotiationManager());
|
||||
|
||||
verify(webMvcConfigurer).configureMessageConverters(converters.capture());
|
||||
verify(webMvcConfigurer).configureContentNegotiation(contentNegotiationConfigurer.capture());
|
||||
@@ -178,29 +184,30 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureExceptionResolvers() throws Exception {
|
||||
List<WebMvcConfigurer> configurers = new ArrayList<>();
|
||||
configurers.add(new WebMvcConfigurer() {
|
||||
public void configureExceptionResolvers() {
|
||||
WebMvcConfigurer configurer = new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
|
||||
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
|
||||
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
|
||||
resolvers.add(new DefaultHandlerExceptionResolver());
|
||||
}
|
||||
});
|
||||
delegatingConfig.setConfigurers(configurers);
|
||||
};
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(configurer));
|
||||
|
||||
HandlerExceptionResolverComposite composite =
|
||||
(HandlerExceptionResolverComposite) delegatingConfig
|
||||
.handlerExceptionResolver(delegatingConfig.mvcContentNegotiationManager());
|
||||
assertThat(composite.getExceptionResolvers().size()).as("Only one custom converter is expected").isEqualTo(1);
|
||||
(HandlerExceptionResolverComposite) webMvcConfig
|
||||
.handlerExceptionResolver(webMvcConfig.mvcContentNegotiationManager());
|
||||
|
||||
assertThat(composite.getExceptionResolvers().size())
|
||||
.as("Only one custom converter is expected")
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePathMatch() throws Exception {
|
||||
final PathMatcher pathMatcher = mock(PathMatcher.class);
|
||||
final UrlPathHelper pathHelper = mock(UrlPathHelper.class);
|
||||
public void configurePathMatcher() {
|
||||
PathMatcher pathMatcher = mock(PathMatcher.class);
|
||||
UrlPathHelper pathHelper = mock(UrlPathHelper.class);
|
||||
|
||||
List<WebMvcConfigurer> configurers = new ArrayList<>();
|
||||
configurers.add(new WebMvcConfigurer() {
|
||||
WebMvcConfigurer configurer = new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void configurePathMatch(PathMatchConfigurer configurer) {
|
||||
configurer.setUseRegisteredSuffixPatternMatch(true)
|
||||
@@ -208,18 +215,122 @@ public class DelegatingWebMvcConfigurationTests {
|
||||
.setUrlPathHelper(pathHelper)
|
||||
.setPathMatcher(pathMatcher);
|
||||
}
|
||||
});
|
||||
delegatingConfig.setConfigurers(configurers);
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/").setViewName("home");
|
||||
}
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/");
|
||||
}
|
||||
};
|
||||
|
||||
RequestMappingHandlerMapping handlerMapping = delegatingConfig.requestMappingHandlerMapping(
|
||||
delegatingConfig.mvcContentNegotiationManager(), delegatingConfig.mvcConversionService(),
|
||||
delegatingConfig.mvcResourceUrlProvider());
|
||||
assertThat(handlerMapping).isNotNull();
|
||||
assertThat(handlerMapping.useRegisteredSuffixPatternMatch()).as("PathMatchConfigurer should configure RegisteredSuffixPatternMatch").isEqualTo(true);
|
||||
assertThat(handlerMapping.useSuffixPatternMatch()).as("PathMatchConfigurer should configure SuffixPatternMatch").isEqualTo(true);
|
||||
assertThat(handlerMapping.useTrailingSlashMatch()).as("PathMatchConfigurer should configure TrailingSlashMatch").isEqualTo(false);
|
||||
assertThat(handlerMapping.getUrlPathHelper()).as("PathMatchConfigurer should configure UrlPathHelper").isEqualTo(pathHelper);
|
||||
assertThat(handlerMapping.getPathMatcher()).as("PathMatchConfigurer should configure PathMatcher").isEqualTo(pathMatcher);
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(configurer));
|
||||
webMvcConfig.setServletContext(servletContext);
|
||||
webMvcConfig.setApplicationContext(new GenericWebApplicationContext(servletContext));
|
||||
|
||||
|
||||
BiConsumer<UrlPathHelper, PathMatcher> configAssertion = (helper, matcher) -> {
|
||||
assertThat(helper).isSameAs(pathHelper);
|
||||
assertThat(matcher).isSameAs(pathMatcher);
|
||||
};
|
||||
|
||||
RequestMappingHandlerMapping annotationsMapping = webMvcConfig.requestMappingHandlerMapping(
|
||||
webMvcConfig.mvcContentNegotiationManager(),
|
||||
webMvcConfig.mvcConversionService(),
|
||||
webMvcConfig.mvcResourceUrlProvider());
|
||||
|
||||
assertThat(annotationsMapping).isNotNull();
|
||||
assertThat(annotationsMapping.useRegisteredSuffixPatternMatch()).isEqualTo(true);
|
||||
assertThat(annotationsMapping.useSuffixPatternMatch()).isEqualTo(true);
|
||||
assertThat(annotationsMapping.useTrailingSlashMatch()).isEqualTo(false);
|
||||
configAssertion.accept(annotationsMapping.getUrlPathHelper(), annotationsMapping.getPathMatcher());
|
||||
|
||||
SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping) webMvcConfig.viewControllerHandlerMapping(
|
||||
webMvcConfig.mvcConversionService(),
|
||||
webMvcConfig.mvcResourceUrlProvider());
|
||||
|
||||
assertThat(mapping).isNotNull();
|
||||
configAssertion.accept(mapping.getUrlPathHelper(), mapping.getPathMatcher());
|
||||
|
||||
mapping = (SimpleUrlHandlerMapping) webMvcConfig.resourceHandlerMapping(
|
||||
webMvcConfig.mvcContentNegotiationManager(),
|
||||
webMvcConfig.mvcConversionService(),
|
||||
webMvcConfig.mvcResourceUrlProvider());
|
||||
|
||||
assertThat(mapping).isNotNull();
|
||||
configAssertion.accept(mapping.getUrlPathHelper(), mapping.getPathMatcher());
|
||||
|
||||
configAssertion.accept(
|
||||
webMvcConfig.mvcResourceUrlProvider().getUrlPathHelper(),
|
||||
webMvcConfig.mvcResourceUrlProvider().getPathMatcher());
|
||||
|
||||
configAssertion.accept(webMvcConfig.mvcUrlPathHelper(), webMvcConfig.mvcPathMatcher());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePathPatternParser() {
|
||||
|
||||
PathPatternParser patternParser = new PathPatternParser();
|
||||
PathMatcher pathMatcher = mock(PathMatcher.class);
|
||||
UrlPathHelper pathHelper = mock(UrlPathHelper.class);
|
||||
|
||||
WebMvcConfigurer configurer = new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void configurePathMatch(PathMatchConfigurer configurer) {
|
||||
configurer.setPatternParser(patternParser)
|
||||
.setUrlPathHelper(pathHelper)
|
||||
.setPathMatcher(pathMatcher);
|
||||
}
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/").setViewName("home");
|
||||
}
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/");
|
||||
}
|
||||
};
|
||||
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(configurer));
|
||||
webMvcConfig.setServletContext(servletContext);
|
||||
webMvcConfig.setApplicationContext(new GenericWebApplicationContext(servletContext));
|
||||
|
||||
|
||||
BiConsumer<UrlPathHelper, PathMatcher> configAssertion = (helper, matcher) -> {
|
||||
assertThat(helper).isNotSameAs(pathHelper);
|
||||
assertThat(matcher).isNotSameAs(pathMatcher);
|
||||
};
|
||||
|
||||
RequestMappingHandlerMapping annotationsMapping = webMvcConfig.requestMappingHandlerMapping(
|
||||
webMvcConfig.mvcContentNegotiationManager(),
|
||||
webMvcConfig.mvcConversionService(),
|
||||
webMvcConfig.mvcResourceUrlProvider());
|
||||
|
||||
assertThat(annotationsMapping).isNotNull();
|
||||
assertThat(annotationsMapping.getPatternParser()).isSameAs(patternParser);
|
||||
configAssertion.accept(annotationsMapping.getUrlPathHelper(), annotationsMapping.getPathMatcher());
|
||||
|
||||
SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping) webMvcConfig.viewControllerHandlerMapping(
|
||||
webMvcConfig.mvcConversionService(),
|
||||
webMvcConfig.mvcResourceUrlProvider());
|
||||
|
||||
assertThat(mapping).isNotNull();
|
||||
assertThat(mapping.getPatternParser()).isSameAs(patternParser);
|
||||
configAssertion.accept(mapping.getUrlPathHelper(), mapping.getPathMatcher());
|
||||
|
||||
mapping = (SimpleUrlHandlerMapping) webMvcConfig.resourceHandlerMapping(
|
||||
webMvcConfig.mvcContentNegotiationManager(),
|
||||
webMvcConfig.mvcConversionService(),
|
||||
webMvcConfig.mvcResourceUrlProvider());
|
||||
|
||||
assertThat(mapping).isNotNull();
|
||||
assertThat(mapping.getPatternParser()).isSameAs(patternParser);
|
||||
configAssertion.accept(mapping.getUrlPathHelper(), mapping.getPathMatcher());
|
||||
|
||||
assertThat(webMvcConfig.mvcResourceUrlProvider().getUrlPathHelper()).isSameAs(pathHelper);
|
||||
assertThat(webMvcConfig.mvcResourceUrlProvider().getPathMatcher()).isSameAs(pathMatcher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -150,10 +150,9 @@ public class WebMvcConfigurationSupportExtensionTests {
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new AssertionError("UserController bean not found"))
|
||||
.getKey();
|
||||
assertThat(info.getPatternsCondition().getPatterns()).isEqualTo(Collections.singleton("/api/user/{id}"));
|
||||
assertThat(info.getPatternValues()).isEqualTo(Collections.singleton("/api/user/{id}"));
|
||||
|
||||
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) this.config.viewControllerHandlerMapping(
|
||||
this.config.mvcPathMatcher(), this.config.mvcUrlPathHelper(),
|
||||
this.config.mvcConversionService(), this.config.mvcResourceUrlProvider());
|
||||
handlerMapping.setApplicationContext(this.context);
|
||||
assertThat(handlerMapping).isNotNull();
|
||||
@@ -171,7 +170,6 @@ public class WebMvcConfigurationSupportExtensionTests {
|
||||
assertThat(chain.getHandler()).isNotNull();
|
||||
|
||||
handlerMapping = (AbstractHandlerMapping) this.config.resourceHandlerMapping(
|
||||
this.config.mvcUrlPathHelper(), this.config.mvcPathMatcher(),
|
||||
this.config.mvcContentNegotiationManager(), this.config.mvcConversionService(),
|
||||
this.config.mvcResourceUrlProvider());
|
||||
handlerMapping.setApplicationContext(this.context);
|
||||
@@ -290,7 +288,6 @@ public class WebMvcConfigurationSupportExtensionTests {
|
||||
|
||||
request.setRequestURI("/resources/foo.gif");
|
||||
SimpleUrlHandlerMapping handlerMapping = (SimpleUrlHandlerMapping) this.config.resourceHandlerMapping(
|
||||
this.config.mvcUrlPathHelper(), this.config.mvcPathMatcher(),
|
||||
this.config.mvcContentNegotiationManager(), this.config.mvcConversionService(),
|
||||
this.config.mvcResourceUrlProvider());
|
||||
handlerMapping.setApplicationContext(this.context);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -156,7 +156,7 @@ public class WebMvcConfigurationSupportTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerAdapter() throws Exception {
|
||||
public void requestMappingHandlerAdapter() {
|
||||
ApplicationContext context = initContext(WebConfig.class);
|
||||
RequestMappingHandlerAdapter adapter = context.getBean(RequestMappingHandlerAdapter.class);
|
||||
List<HttpMessageConverter<?>> converters = adapter.getMessageConverters();
|
||||
@@ -196,7 +196,7 @@ public class WebMvcConfigurationSupportTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uriComponentsContributor() throws Exception {
|
||||
public void uriComponentsContributor() {
|
||||
ApplicationContext context = initContext(WebConfig.class);
|
||||
CompositeUriComponentsContributor uriComponentsContributor = context.getBean(
|
||||
MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME,
|
||||
@@ -207,7 +207,7 @@ public class WebMvcConfigurationSupportTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handlerExceptionResolver() throws Exception {
|
||||
public void handlerExceptionResolver() {
|
||||
ApplicationContext context = initContext(WebConfig.class);
|
||||
HandlerExceptionResolverComposite compositeResolver =
|
||||
context.getBean("handlerExceptionResolver", HandlerExceptionResolverComposite.class);
|
||||
@@ -300,7 +300,7 @@ public class WebMvcConfigurationSupportTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultPathMatchConfiguration() throws Exception {
|
||||
public void defaultPathMatchConfiguration() {
|
||||
ApplicationContext context = initContext(WebConfig.class);
|
||||
UrlPathHelper urlPathHelper = context.getBean(UrlPathHelper.class);
|
||||
PathMatcher pathMatcher = context.getBean(PathMatcher.class);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -35,14 +36,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class DefaultServerRequestBuilderTests {
|
||||
class DefaultServerRequestBuilderTests {
|
||||
|
||||
private final List<HttpMessageConverter<?>> messageConverters =
|
||||
Collections.singletonList(new StringHttpMessageConverter());
|
||||
|
||||
private final List<HttpMessageConverter<?>> messageConverters = Collections.singletonList(
|
||||
new StringHttpMessageConverter());
|
||||
|
||||
@Test
|
||||
public void from() throws ServletException, IOException {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "https://example.com");
|
||||
void from() throws ServletException, IOException {
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("POST", "https://example.com", true);
|
||||
request.addHeader("foo", "bar");
|
||||
|
||||
ServerRequest other = ServerRequest.create(request, messageConverters);
|
||||
@@ -65,7 +67,7 @@ public class DefaultServerRequestBuilderTests {
|
||||
assertThat(result.cookies().size()).isEqualTo(2);
|
||||
assertThat(result.cookies().getFirst("foo").getValue()).isEqualTo("bar");
|
||||
assertThat(result.cookies().getFirst("baz").getValue()).isEqualTo("qux");
|
||||
assertThat(result.attributes().size()).isEqualTo(2);
|
||||
assertThat(result.attributes().size()).isEqualTo(other.attributes().size() + 2);
|
||||
assertThat(result.attributes().get("foo")).isEqualTo("bar");
|
||||
assertThat(result.attributes().get("baz")).isEqualTo("qux");
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpSession;
|
||||
@@ -66,23 +67,22 @@ import static org.springframework.web.testfixture.http.server.reactive.MockServe
|
||||
* @author Arjen Poutsma
|
||||
* @since 5.1
|
||||
*/
|
||||
public class DefaultServerRequestTests {
|
||||
class DefaultServerRequestTests {
|
||||
|
||||
private final List<HttpMessageConverter<?>> messageConverters = Collections.singletonList(
|
||||
new StringHttpMessageConverter());
|
||||
|
||||
@Test
|
||||
public void method() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("HEAD", "/");
|
||||
DefaultServerRequest request =
|
||||
new DefaultServerRequest(servletRequest, this.messageConverters);
|
||||
void method() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("HEAD", "/", true);
|
||||
DefaultServerRequest request = new DefaultServerRequest(servletRequest, this.messageConverters);
|
||||
|
||||
assertThat(request.method()).isEqualTo(HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uri() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void uri() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setServerName("example.com");
|
||||
servletRequest.setScheme("https");
|
||||
servletRequest.setServerPort(443);
|
||||
@@ -94,8 +94,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uriBuilder() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
void uriBuilder() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/path", true);
|
||||
servletRequest.setQueryString("a=1");
|
||||
|
||||
DefaultServerRequest request =
|
||||
@@ -110,8 +110,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attribute() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void attribute() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setAttribute("foo", "bar");
|
||||
|
||||
DefaultServerRequest request =
|
||||
@@ -121,8 +121,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void params() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void params() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setParameter("foo", "bar");
|
||||
|
||||
DefaultServerRequest request =
|
||||
@@ -132,11 +132,11 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartData() throws Exception {
|
||||
void multipartData() throws Exception {
|
||||
MockPart formPart = new MockPart("form", "foo".getBytes(UTF_8));
|
||||
MockPart filePart = new MockPart("file", "foo.txt", "foo".getBytes(UTF_8));
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("POST", "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("POST", "/", true);
|
||||
servletRequest.addPart(formPart);
|
||||
servletRequest.addPart(filePart);
|
||||
|
||||
@@ -151,8 +151,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyQueryParam() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void emptyQueryParam() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setParameter("foo", "");
|
||||
|
||||
DefaultServerRequest request =
|
||||
@@ -162,8 +162,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void absentQueryParam() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void absentQueryParam() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setParameter("foo", "");
|
||||
|
||||
DefaultServerRequest request =
|
||||
@@ -173,8 +173,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathVariable() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void pathVariable() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
Map<String, String> pathVariables = Collections.singletonMap("foo", "bar");
|
||||
servletRequest
|
||||
.setAttribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVariables);
|
||||
@@ -186,8 +186,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathVariableNotFound() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void pathVariableNotFound() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
Map<String, String> pathVariables = Collections.singletonMap("foo", "bar");
|
||||
servletRequest
|
||||
.setAttribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVariables);
|
||||
@@ -200,8 +200,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathVariables() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void pathVariables() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
Map<String, String> pathVariables = Collections.singletonMap("foo", "bar");
|
||||
servletRequest
|
||||
.setAttribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVariables);
|
||||
@@ -213,7 +213,7 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void header() {
|
||||
void header() {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
List<MediaType> accept =
|
||||
Collections.singletonList(MediaType.APPLICATION_JSON);
|
||||
@@ -229,7 +229,7 @@ public class DefaultServerRequestTests {
|
||||
List<HttpRange> range = Collections.singletonList(HttpRange.createByteRange(0, 42));
|
||||
httpHeaders.setRange(range);
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
httpHeaders.forEach(servletRequest::addHeader);
|
||||
servletRequest.setContentType(MediaType.TEXT_PLAIN_VALUE);
|
||||
|
||||
@@ -247,10 +247,10 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cookies() {
|
||||
void cookies() {
|
||||
Cookie cookie = new Cookie("foo", "bar");
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setCookies(cookie);
|
||||
|
||||
DefaultServerRequest request = new DefaultServerRequest(servletRequest,
|
||||
@@ -264,8 +264,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bodyClass() throws Exception {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void bodyClass() throws Exception {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setContentType(MediaType.TEXT_PLAIN_VALUE);
|
||||
servletRequest.setContent("foo".getBytes(UTF_8));
|
||||
|
||||
@@ -277,8 +277,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bodyParameterizedTypeReference() throws Exception {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void bodyParameterizedTypeReference() throws Exception {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
servletRequest.setContent("[\"foo\",\"bar\"]".getBytes(UTF_8));
|
||||
|
||||
@@ -292,8 +292,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bodyUnacceptable() throws Exception {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void bodyUnacceptable() throws Exception {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.setContentType(MediaType.TEXT_PLAIN_VALUE);
|
||||
servletRequest.setContent("foo".getBytes(UTF_8));
|
||||
|
||||
@@ -305,8 +305,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void session() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void session() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
servletRequest.setSession(session);
|
||||
|
||||
@@ -318,8 +318,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void principal() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
void principal() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
Principal principal = new Principal() {
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -336,7 +336,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkNotModifiedTimestamp(String method) throws Exception {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
servletRequest.addHeader(HttpHeaders.IF_MODIFIED_SINCE, now.toEpochMilli());
|
||||
|
||||
@@ -352,7 +352,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkModifiedTimestamp(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
Instant oneMinuteAgo = now.minus(1, ChronoUnit.MINUTES);
|
||||
servletRequest.addHeader(HttpHeaders.IF_MODIFIED_SINCE, oneMinuteAgo.toEpochMilli());
|
||||
@@ -366,7 +366,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkNotModifiedETag(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String eTag = "\"Foo\"";
|
||||
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, eTag);
|
||||
|
||||
@@ -382,7 +382,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkNotModifiedETagWithSeparatorChars(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String eTag = "\"Foo, Bar\"";
|
||||
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, eTag);
|
||||
|
||||
@@ -398,7 +398,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkModifiedETag(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String currentETag = "\"Foo\"";
|
||||
String oldEtag = "Bar";
|
||||
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, oldEtag);
|
||||
@@ -412,7 +412,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkNotModifiedUnpaddedETag(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String eTag = "Foo";
|
||||
String paddedEtag = String.format("\"%s\"", eTag);
|
||||
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, paddedEtag);
|
||||
@@ -429,7 +429,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkModifiedUnpaddedETag(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String currentETag = "Foo";
|
||||
String oldEtag = "Bar";
|
||||
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, oldEtag);
|
||||
@@ -443,7 +443,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkNotModifiedWildcardIsIgnored(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String eTag = "\"Foo\"";
|
||||
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, "*");
|
||||
DefaultServerRequest request = new DefaultServerRequest(servletRequest, this.messageConverters);
|
||||
@@ -455,7 +455,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkNotModifiedETagAndTimestamp(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String eTag = "\"Foo\"";
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, eTag);
|
||||
@@ -475,7 +475,7 @@ public class DefaultServerRequestTests {
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkNotModifiedETagAndModifiedTimestamp(String method) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String eTag = "\"Foo\"";
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
Instant oneMinuteAgo = now.minus(1, ChronoUnit.MINUTES);
|
||||
@@ -498,8 +498,8 @@ public class DefaultServerRequestTests {
|
||||
}
|
||||
|
||||
@ParameterizedHttpMethodTest
|
||||
void checkModifiedETagAndNotModifiedTimestamp(String method) throws Exception {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest(method, "/");
|
||||
void checkModifiedETagAndNotModifiedTimestamp(String method) {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest(method, "/", true);
|
||||
String currentETag = "\"Foo\"";
|
||||
String oldEtag = "\"Bar\"";
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -25,26 +25,20 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class PathResourceLookupFunctionTests {
|
||||
class PathResourceLookupFunctionTests {
|
||||
|
||||
@Test
|
||||
public void normal() throws Exception {
|
||||
ClassPathResource location =
|
||||
new ClassPathResource("org/springframework/web/servlet/function/");
|
||||
|
||||
PathResourceLookupFunction function =
|
||||
new PathResourceLookupFunction("/resources/**", location);
|
||||
|
||||
MockHttpServletRequest servletRequest =
|
||||
new MockHttpServletRequest("GET", "/resources/response.txt");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
void normal() throws Exception {
|
||||
ClassPathResource location = new ClassPathResource("org/springframework/web/servlet/function/");
|
||||
PathResourceLookupFunction function = new PathResourceLookupFunction("/resources/**", location);
|
||||
ServerRequest request = initRequest("GET", "/resources/response.txt");
|
||||
|
||||
Optional<Resource> result = function.apply(request);
|
||||
assertThat(result.isPresent()).isTrue();
|
||||
@@ -54,44 +48,30 @@ public class PathResourceLookupFunctionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subPath() throws Exception {
|
||||
ClassPathResource location =
|
||||
new ClassPathResource("org/springframework/web/servlet/function/");
|
||||
|
||||
PathResourceLookupFunction function =
|
||||
new PathResourceLookupFunction("/resources/**", location);
|
||||
|
||||
MockHttpServletRequest servletRequest =
|
||||
new MockHttpServletRequest("GET", "/resources/child/response.txt");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
void subPath() throws Exception {
|
||||
ClassPathResource location = new ClassPathResource("org/springframework/web/servlet/function/");
|
||||
PathResourceLookupFunction function = new PathResourceLookupFunction("/resources/**", location);
|
||||
ServerRequest request = initRequest("GET", "/resources/child/response.txt");
|
||||
|
||||
Optional<Resource> result = function.apply(request);
|
||||
assertThat(result.isPresent()).isTrue();
|
||||
|
||||
File expected =
|
||||
new ClassPathResource("org/springframework/web/servlet/function/child/response.txt")
|
||||
.getFile();
|
||||
File expected = new ClassPathResource("org/springframework/web/servlet/function/child/response.txt").getFile();
|
||||
assertThat(result.get().getFile()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notFound() {
|
||||
ClassPathResource location =
|
||||
new ClassPathResource("org/springframework/web/reactive/function/server/");
|
||||
|
||||
PathResourceLookupFunction function =
|
||||
new PathResourceLookupFunction("/resources/**", location);
|
||||
|
||||
MockHttpServletRequest servletRequest =
|
||||
new MockHttpServletRequest("GET", "/resources/foo.txt");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
void notFound() {
|
||||
ClassPathResource location = new ClassPathResource("org/springframework/web/reactive/function/server/");
|
||||
PathResourceLookupFunction function = new PathResourceLookupFunction("/resources/**", location);
|
||||
ServerRequest request = initRequest("GET", "/resources/foo.txt");
|
||||
|
||||
Optional<Resource> result = function.apply(request);
|
||||
assertThat(result.isPresent()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeResourceLookupFunction() throws Exception {
|
||||
void composeResourceLookupFunction() throws Exception {
|
||||
ClassPathResource defaultResource = new ClassPathResource("response.txt", getClass());
|
||||
|
||||
Function<ServerRequest, Optional<Resource>> lookupFunction =
|
||||
@@ -108,8 +88,7 @@ public class PathResourceLookupFunctionTests {
|
||||
}
|
||||
});
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/resources/foo");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
ServerRequest request = initRequest("GET", "/resources/foo");
|
||||
|
||||
Optional<Resource> result = customLookupFunction.apply(request);
|
||||
assertThat(result.isPresent()).isTrue();
|
||||
@@ -117,4 +96,10 @@ public class PathResourceLookupFunctionTests {
|
||||
assertThat(result.get().getFile()).isEqualTo(defaultResource.getFile());
|
||||
}
|
||||
|
||||
private ServerRequest initRequest(String httpMethod, String requestUri) {
|
||||
return new DefaultServerRequest(
|
||||
PathPatternsTestUtils.initRequest(httpMethod, requestUri, true),
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -28,18 +29,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class RequestPredicateTests {
|
||||
class RequestPredicateTests {
|
||||
|
||||
private ServerRequest request;
|
||||
|
||||
@BeforeEach
|
||||
public void createRequest() {
|
||||
this.request = new DefaultServerRequest(new MockHttpServletRequest(),
|
||||
Collections.emptyList());
|
||||
void createRequest() {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
this.request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void and() {
|
||||
void and() {
|
||||
RequestPredicate predicate1 = request -> true;
|
||||
RequestPredicate predicate2 = request -> true;
|
||||
RequestPredicate predicate3 = request -> false;
|
||||
@@ -50,7 +51,7 @@ public class RequestPredicateTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negate() {
|
||||
void negate() {
|
||||
RequestPredicate predicate = request -> false;
|
||||
RequestPredicate negated = predicate.negate();
|
||||
|
||||
@@ -63,7 +64,7 @@ public class RequestPredicateTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void or() {
|
||||
void or() {
|
||||
RequestPredicate predicate1 = request -> true;
|
||||
RequestPredicate predicate2 = request -> false;
|
||||
RequestPredicate predicate3 = request -> false;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.web.servlet.function;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -24,245 +25,189 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.http.MediaType.TEXT_XML_VALUE;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class RequestPredicatesTests {
|
||||
class RequestPredicatesTests {
|
||||
|
||||
@Test
|
||||
public void all() {
|
||||
void all() {
|
||||
RequestPredicate predicate = RequestPredicates.all();
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest request = initRequest("GET", "/");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void method() {
|
||||
void method() {
|
||||
HttpMethod httpMethod = HttpMethod.GET;
|
||||
RequestPredicate predicate = RequestPredicates.method(httpMethod);
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "https://example.com");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest.setMethod("POST");
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
assertThat(predicate.test(initRequest("GET", "https://example.com"))).isTrue();
|
||||
assertThat(predicate.test(initRequest("POST", "https://example.com"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodCorsPreFlight() {
|
||||
void methodCorsPreFlight() {
|
||||
RequestPredicate predicate = RequestPredicates.method(HttpMethod.PUT);
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("OPTIONS", "https://example.com");
|
||||
servletRequest.addHeader("Origin", "https://example.com");
|
||||
servletRequest.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PUT");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest request = initRequest("OPTIONS", "https://example.com", servletRequest -> {
|
||||
servletRequest.addHeader("Origin", "https://example.com");
|
||||
servletRequest.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PUT");
|
||||
});
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest.removeHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD);
|
||||
servletRequest.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST");
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
request = initRequest("OPTIONS", "https://example.com", servletRequest -> {
|
||||
servletRequest.removeHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD);
|
||||
servletRequest.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST");
|
||||
});
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methods() {
|
||||
void methods() {
|
||||
RequestPredicate predicate = RequestPredicates.methods(HttpMethod.GET, HttpMethod.HEAD);
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "https://example.com");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest.setMethod("HEAD");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest.setMethod("POST");
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
assertThat(predicate.test(initRequest("GET", "https://example.com"))).isTrue();
|
||||
assertThat(predicate.test(initRequest("HEAD", "https://example.com"))).isTrue();
|
||||
assertThat(predicate.test(initRequest("POST", "https://example.com"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allMethods() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
|
||||
void allMethods() {
|
||||
RequestPredicate predicate = RequestPredicates.GET("/p*");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("GET", "/path"))).isTrue();
|
||||
|
||||
predicate = RequestPredicates.HEAD("/p*");
|
||||
servletRequest.setMethod("HEAD");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("HEAD", "/path"))).isTrue();
|
||||
|
||||
predicate = RequestPredicates.POST("/p*");
|
||||
servletRequest.setMethod("POST");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("POST", "/path"))).isTrue();
|
||||
|
||||
predicate = RequestPredicates.PUT("/p*");
|
||||
servletRequest.setMethod("PUT");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("PUT", "/path"))).isTrue();
|
||||
|
||||
predicate = RequestPredicates.PATCH("/p*");
|
||||
servletRequest.setMethod("PATCH");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("PATCH", "/path"))).isTrue();
|
||||
|
||||
predicate = RequestPredicates.DELETE("/p*");
|
||||
servletRequest.setMethod("DELETE");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("DELETE", "/path"))).isTrue();
|
||||
|
||||
predicate = RequestPredicates.OPTIONS("/p*");
|
||||
servletRequest.setMethod("OPTIONS");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("OPTIONS", "/path"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void path() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
void path() {
|
||||
RequestPredicate predicate = RequestPredicates.path("/p*");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest = new MockHttpServletRequest("GET", "/foo");
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
assertThat(predicate.test(initRequest("GET", "/path"))).isTrue();
|
||||
assertThat(predicate.test(initRequest("GET", "/foo"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servletPath() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo/bar");
|
||||
servletRequest.setServletPath("/foo");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
void contextPath() {
|
||||
RequestPredicate predicate = RequestPredicates.path("/bar");
|
||||
|
||||
ServerRequest request = new DefaultServerRequest(
|
||||
PathPatternsTestUtils.initRequest("GET", "/foo", "/bar", true),
|
||||
Collections.emptyList());
|
||||
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest = new MockHttpServletRequest("GET", "/foo");
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
request = initRequest("GET", "/foo");
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathNoLeadingSlash() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
void pathNoLeadingSlash() {
|
||||
RequestPredicate predicate = RequestPredicates.path("p*");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("GET", "/path"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathEncoded() {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo%20bar");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
|
||||
void pathEncoded() {
|
||||
RequestPredicate predicate = RequestPredicates.path("/foo bar");
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest = new MockHttpServletRequest();
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
assertThat(predicate.test(initRequest("GET", "/foo%20bar"))).isTrue();
|
||||
assertThat(predicate.test(initRequest("GET", ""))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathPredicates() {
|
||||
void pathPredicates() {
|
||||
PathPatternParser parser = new PathPatternParser();
|
||||
parser.setCaseSensitive(false);
|
||||
Function<String, RequestPredicate> pathPredicates = RequestPredicates.pathPredicates(parser);
|
||||
|
||||
RequestPredicate predicate = pathPredicates.apply("/P*");
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("GET", "/path"))).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void headers() {
|
||||
void headers() {
|
||||
String name = "MyHeader";
|
||||
String value = "MyValue";
|
||||
RequestPredicate predicate =
|
||||
RequestPredicates.headers(
|
||||
headers -> headers.header(name).equals(Collections.singletonList(value)));
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
servletRequest.addHeader(name, value);
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest request = initRequest("GET", "/path", req -> req.addHeader(name, value));
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest = new MockHttpServletRequest();
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
assertThat(predicate.test(initRequest("GET", ""))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headersCors() {
|
||||
void headersCors() {
|
||||
RequestPredicate predicate = RequestPredicates.headers(headers -> false);
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("OPTIONS", "https://example.com");
|
||||
servletRequest.addHeader("Origin", "https://example.com");
|
||||
servletRequest.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PUT");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest request = initRequest("OPTIONS", "https://example.com", servletRequest -> {
|
||||
servletRequest.addHeader("Origin", "https://example.com");
|
||||
servletRequest.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PUT");
|
||||
});
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentType() {
|
||||
void contentType() {
|
||||
MediaType json = MediaType.APPLICATION_JSON;
|
||||
RequestPredicate predicate = RequestPredicates.contentType(json);
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
servletRequest.setContentType(json.toString());
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
|
||||
ServerRequest request = initRequest("GET", "/path", req -> req.setContentType(json.toString()));
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest = new MockHttpServletRequest();
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
assertThat(predicate.test(initRequest("GET", ""))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accept() {
|
||||
void accept() {
|
||||
MediaType json = MediaType.APPLICATION_JSON;
|
||||
RequestPredicate predicate = RequestPredicates.accept(json);
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
servletRequest.addHeader("Accept", json.toString());
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest request = initRequest("GET", "/path", req -> req.addHeader("Accept", json.toString()));
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest = new MockHttpServletRequest();
|
||||
servletRequest.addHeader("Accept", TEXT_XML_VALUE);
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
request = initRequest("GET", "", req -> req.addHeader("Accept", TEXT_XML_VALUE));
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathExtension() {
|
||||
void pathExtension() {
|
||||
RequestPredicate predicate = RequestPredicates.pathExtension("txt");
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/file.txt");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
servletRequest = new MockHttpServletRequest("GET", "/FILE.TXT");
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
assertThat(predicate.test(initRequest("GET", "/file.txt"))).isTrue();
|
||||
assertThat(predicate.test(initRequest("GET", "/FILE.TXT"))).isTrue();
|
||||
|
||||
predicate = RequestPredicates.pathExtension("bar");
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
assertThat(predicate.test(initRequest("GET", "/FILE.TXT"))).isFalse();
|
||||
|
||||
servletRequest = new MockHttpServletRequest("GET", "/file.foo");
|
||||
request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
assertThat(predicate.test(initRequest("GET", "/file.foo"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void param() {
|
||||
void param() {
|
||||
RequestPredicate predicate = RequestPredicates.param("foo", "bar");
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path");
|
||||
servletRequest.addParameter("foo", "bar");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest request = initRequest("GET", "/path", req -> req.addParameter("foo", "bar"));
|
||||
assertThat(predicate.test(request)).isTrue();
|
||||
|
||||
predicate = RequestPredicates.param("foo", s -> s.equals("bar"));
|
||||
@@ -275,4 +220,17 @@ public class RequestPredicatesTests {
|
||||
assertThat(predicate.test(request)).isFalse();
|
||||
}
|
||||
|
||||
|
||||
private ServerRequest initRequest(String httpMethod, String requestUri) {
|
||||
return initRequest(httpMethod, requestUri, null);
|
||||
}
|
||||
|
||||
private ServerRequest initRequest(
|
||||
String httpMethod, String requestUri, @Nullable Consumer<MockHttpServletRequest> initializer) {
|
||||
|
||||
return new DefaultServerRequest(
|
||||
PathPatternsTestUtils.initRequest(httpMethod, null, requestUri, true, initializer),
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
@@ -35,10 +34,10 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.ResourceHttpMessageConverter;
|
||||
import org.springframework.http.converter.ResourceRegionHttpMessageConverter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
@@ -61,19 +60,13 @@ public class ResourceHandlerFunctionTests {
|
||||
public void createContext() {
|
||||
this.messageConverter = new ResourceHttpMessageConverter();
|
||||
ResourceRegionHttpMessageConverter regionConverter = new ResourceRegionHttpMessageConverter();
|
||||
this.context = new ServerResponse.Context() {
|
||||
@Override
|
||||
public List<HttpMessageConverter<?>> messageConverters() {
|
||||
return Arrays.asList(messageConverter, regionConverter);
|
||||
}
|
||||
|
||||
};
|
||||
this.context = () -> Arrays.asList(messageConverter, regionConverter);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void get() throws IOException, ServletException {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.singletonList(messageConverter));
|
||||
|
||||
ServerResponse response = this.handlerFunction.handle(request);
|
||||
@@ -97,7 +90,7 @@ public class ResourceHandlerFunctionTests {
|
||||
|
||||
@Test
|
||||
public void getRange() throws IOException, ServletException {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.addHeader("Range", "bytes=0-5");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.singletonList(messageConverter));
|
||||
|
||||
@@ -126,7 +119,7 @@ public class ResourceHandlerFunctionTests {
|
||||
|
||||
@Test
|
||||
public void getInvalidRange() throws IOException, ServletException {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.addHeader("Range", "bytes=0-10, 0-10, 0-10, 0-10, 0-10, 0-10");
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.singletonList(messageConverter));
|
||||
|
||||
@@ -152,7 +145,7 @@ public class ResourceHandlerFunctionTests {
|
||||
|
||||
@Test
|
||||
public void head() throws IOException, ServletException {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("HEAD", "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("HEAD", "/", true);
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.singletonList(messageConverter));
|
||||
|
||||
ServerResponse response = this.handlerFunction.handle(request);
|
||||
@@ -174,10 +167,9 @@ public class ResourceHandlerFunctionTests {
|
||||
assertThat(servletResponse.getContentLength()).isEqualTo(this.resource.contentLength());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void options() throws ServletException, IOException {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("OPTIONS", "/");
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("OPTIONS", "/", true);
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.singletonList(messageConverter));
|
||||
|
||||
ServerResponse response = this.handlerFunction.handle(request);
|
||||
@@ -194,5 +186,4 @@ public class ResourceHandlerFunctionTests {
|
||||
assertThat(actualBytes.length).isEqualTo(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,6 +18,7 @@ package org.springframework.web.servlet.function;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -25,6 +26,8 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
@@ -36,10 +39,10 @@ import static org.springframework.web.servlet.function.RequestPredicates.HEAD;
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class RouterFunctionBuilderTests {
|
||||
class RouterFunctionBuilderTests {
|
||||
|
||||
@Test
|
||||
public void route() {
|
||||
void route() {
|
||||
RouterFunction<ServerResponse> route = RouterFunctions.route()
|
||||
.GET("/foo", request -> ServerResponse.ok().build())
|
||||
.POST("/", RequestPredicates.contentType(MediaType.TEXT_PLAIN),
|
||||
@@ -47,8 +50,7 @@ public class RouterFunctionBuilderTests {
|
||||
.route(HEAD("/foo"), request -> ServerResponse.accepted().build())
|
||||
.build();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo");
|
||||
ServerRequest getFooRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest getFooRequest = initRequest("GET", "/foo");
|
||||
|
||||
Optional<Integer> responseStatus = route.route(getFooRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, getFooRequest))
|
||||
@@ -56,8 +58,7 @@ public class RouterFunctionBuilderTests {
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(200);
|
||||
|
||||
servletRequest = new MockHttpServletRequest("HEAD", "/foo");
|
||||
ServerRequest headFooRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest headFooRequest = initRequest("HEAD", "/foo");
|
||||
|
||||
responseStatus = route.route(headFooRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, getFooRequest))
|
||||
@@ -65,9 +66,7 @@ public class RouterFunctionBuilderTests {
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(202);
|
||||
|
||||
servletRequest = new MockHttpServletRequest("POST", "/");
|
||||
servletRequest.setContentType("text/plain");
|
||||
ServerRequest barRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest barRequest = initRequest("POST", "/", req -> req.setContentType("text/plain"));
|
||||
|
||||
responseStatus = route.route(barRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, barRequest))
|
||||
@@ -75,8 +74,7 @@ public class RouterFunctionBuilderTests {
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(204);
|
||||
|
||||
servletRequest = new MockHttpServletRequest("POST", "/");
|
||||
ServerRequest invalidRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest invalidRequest = initRequest("POST", "/");
|
||||
|
||||
responseStatus = route.route(invalidRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, invalidRequest))
|
||||
@@ -84,7 +82,6 @@ public class RouterFunctionBuilderTests {
|
||||
.map(HttpStatus::value);
|
||||
|
||||
assertThat(responseStatus.isPresent()).isFalse();
|
||||
|
||||
}
|
||||
|
||||
private static ServerResponse handle(HandlerFunction<ServerResponse> handlerFunction,
|
||||
@@ -98,7 +95,7 @@ public class RouterFunctionBuilderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resources() {
|
||||
void resources() {
|
||||
Resource resource = new ClassPathResource("/org/springframework/web/servlet/function/");
|
||||
assertThat(resource.exists()).isTrue();
|
||||
|
||||
@@ -106,9 +103,7 @@ public class RouterFunctionBuilderTests {
|
||||
.resources("/resources/**", resource)
|
||||
.build();
|
||||
|
||||
MockHttpServletRequest servletRequest =
|
||||
new MockHttpServletRequest("GET", "/resources/response.txt");
|
||||
ServerRequest resourceRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest resourceRequest = initRequest("GET", "/resources/response.txt");
|
||||
|
||||
Optional<Integer> responseStatus = route.route(resourceRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, resourceRequest))
|
||||
@@ -116,8 +111,7 @@ public class RouterFunctionBuilderTests {
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(200);
|
||||
|
||||
servletRequest = new MockHttpServletRequest("POST", "/resources/foo.txt");
|
||||
ServerRequest invalidRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest invalidRequest = initRequest("POST", "/resources/foo.txt");
|
||||
|
||||
responseStatus = route.route(invalidRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, invalidRequest))
|
||||
@@ -127,7 +121,7 @@ public class RouterFunctionBuilderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nest() {
|
||||
void nest() {
|
||||
RouterFunction<ServerResponse> route = RouterFunctions.route()
|
||||
.path("/foo", builder ->
|
||||
builder.path("/bar",
|
||||
@@ -136,8 +130,7 @@ public class RouterFunctionBuilderTests {
|
||||
.build()))
|
||||
.build();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo/bar/baz");
|
||||
ServerRequest fooRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest fooRequest = initRequest("GET", "/foo/bar/baz");
|
||||
|
||||
Optional<Integer> responseStatus = route.route(fooRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, fooRequest))
|
||||
@@ -147,7 +140,7 @@ public class RouterFunctionBuilderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filters() {
|
||||
void filters() {
|
||||
AtomicInteger filterCount = new AtomicInteger();
|
||||
|
||||
RouterFunction<ServerResponse> route = RouterFunctions.route()
|
||||
@@ -178,8 +171,7 @@ public class RouterFunctionBuilderTests {
|
||||
.build())
|
||||
.build();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo");
|
||||
ServerRequest fooRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest fooRequest = initRequest("GET", "/foo");
|
||||
|
||||
route.route(fooRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, fooRequest));
|
||||
@@ -187,8 +179,7 @@ public class RouterFunctionBuilderTests {
|
||||
|
||||
filterCount.set(0);
|
||||
|
||||
servletRequest = new MockHttpServletRequest("GET", "/bar");
|
||||
ServerRequest barRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
ServerRequest barRequest = initRequest("GET", "/bar");
|
||||
|
||||
Optional<Integer> responseStatus = route.route(barRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, barRequest))
|
||||
@@ -197,4 +188,16 @@ public class RouterFunctionBuilderTests {
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(500);
|
||||
}
|
||||
|
||||
|
||||
private ServerRequest initRequest(String httpMethod, String requestUri) {
|
||||
return initRequest(httpMethod, requestUri, null);
|
||||
}
|
||||
|
||||
private ServerRequest initRequest(
|
||||
String httpMethod, String requestUri, @Nullable Consumer<MockHttpServletRequest> consumer) {
|
||||
|
||||
return new DefaultServerRequest(
|
||||
PathPatternsTestUtils.initRequest(httpMethod, null, requestUri, true, consumer), emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,22 +16,26 @@
|
||||
|
||||
package org.springframework.web.servlet.function;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class RouterFunctionTests {
|
||||
class RouterFunctionTests {
|
||||
|
||||
private final ServerRequest request = new DefaultServerRequest(
|
||||
PathPatternsTestUtils.initRequest("GET", "", true), Collections.emptyList());
|
||||
|
||||
|
||||
@Test
|
||||
public void and() {
|
||||
void and() {
|
||||
HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().build();
|
||||
RouterFunction<ServerResponse> routerFunction1 = request -> Optional.empty();
|
||||
RouterFunction<ServerResponse> routerFunction2 = request -> Optional.of(handlerFunction);
|
||||
@@ -39,9 +43,6 @@ public class RouterFunctionTests {
|
||||
RouterFunction<ServerResponse> result = routerFunction1.and(routerFunction2);
|
||||
assertThat(result).isNotNull();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
|
||||
Optional<HandlerFunction<ServerResponse>> resultHandlerFunction = result.route(request);
|
||||
assertThat(resultHandlerFunction.isPresent()).isTrue();
|
||||
assertThat(resultHandlerFunction.get()).isEqualTo(handlerFunction);
|
||||
@@ -49,7 +50,7 @@ public class RouterFunctionTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void andOther() {
|
||||
void andOther() {
|
||||
HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().body("42");
|
||||
RouterFunction<?> routerFunction1 = request -> Optional.empty();
|
||||
RouterFunction<ServerResponse> routerFunction2 = request -> Optional.of(handlerFunction);
|
||||
@@ -57,9 +58,6 @@ public class RouterFunctionTests {
|
||||
RouterFunction<?> result = routerFunction1.andOther(routerFunction2);
|
||||
assertThat(result).isNotNull();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
|
||||
Optional<? extends HandlerFunction<?>> resultHandlerFunction = result.route(request);
|
||||
assertThat(resultHandlerFunction.isPresent()).isTrue();
|
||||
assertThat(resultHandlerFunction.get()).isEqualTo(handlerFunction);
|
||||
@@ -67,23 +65,20 @@ public class RouterFunctionTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void andRoute() {
|
||||
void andRoute() {
|
||||
RouterFunction<ServerResponse> routerFunction1 = request -> Optional.empty();
|
||||
RequestPredicate requestPredicate = request -> true;
|
||||
|
||||
RouterFunction<ServerResponse> result = routerFunction1.andRoute(requestPredicate, this::handlerMethod);
|
||||
assertThat(result).isNotNull();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
|
||||
Optional<? extends HandlerFunction<?>> resultHandlerFunction = result.route(request);
|
||||
assertThat(resultHandlerFunction.isPresent()).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void filter() {
|
||||
void filter() {
|
||||
String string = "42";
|
||||
HandlerFunction<EntityResponse<String>> handlerFunction =
|
||||
request -> EntityResponse.fromObject(string).build();
|
||||
@@ -100,9 +95,6 @@ public class RouterFunctionTests {
|
||||
RouterFunction<EntityResponse<Integer>> result = routerFunction.filter(filterFunction);
|
||||
assertThat(result).isNotNull();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, emptyList());
|
||||
|
||||
Optional<EntityResponse<Integer>> resultHandlerFunction = result.route(request)
|
||||
.map(hf -> {
|
||||
try {
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -32,12 +32,14 @@ import static org.mockito.Mockito.mock;
|
||||
*/
|
||||
public class RouterFunctionsTests {
|
||||
|
||||
private final ServerRequest request = new DefaultServerRequest(
|
||||
PathPatternsTestUtils.initRequest("GET", "", true), Collections.emptyList());
|
||||
|
||||
|
||||
@Test
|
||||
public void routeMatch() {
|
||||
HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().build();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
RequestPredicate requestPredicate = mock(RequestPredicate.class);
|
||||
given(requestPredicate.test(request)).willReturn(true);
|
||||
|
||||
@@ -54,8 +56,6 @@ public class RouterFunctionsTests {
|
||||
public void routeNoMatch() {
|
||||
HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().build();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
RequestPredicate requestPredicate = mock(RequestPredicate.class);
|
||||
given(requestPredicate.test(request)).willReturn(false);
|
||||
|
||||
@@ -71,8 +71,6 @@ public class RouterFunctionsTests {
|
||||
HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().build();
|
||||
RouterFunction<ServerResponse> routerFunction = request -> Optional.of(handlerFunction);
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
RequestPredicate requestPredicate = mock(RequestPredicate.class);
|
||||
given(requestPredicate.nest(request)).willReturn(Optional.of(request));
|
||||
|
||||
@@ -89,8 +87,6 @@ public class RouterFunctionsTests {
|
||||
HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().build();
|
||||
RouterFunction<ServerResponse> routerFunction = request -> Optional.of(handlerFunction);
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList());
|
||||
RequestPredicate requestPredicate = mock(RequestPredicate.class);
|
||||
given(requestPredicate.nest(request)).willReturn(Optional.empty());
|
||||
|
||||
|
||||
@@ -16,22 +16,18 @@
|
||||
|
||||
package org.springframework.web.servlet.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.http.server.RequestPath;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
@@ -39,6 +35,8 @@ import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.support.WebContentGenerator;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -50,205 +48,214 @@ import static org.mockito.Mockito.mock;
|
||||
*/
|
||||
class CorsAbstractHandlerMappingTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private AbstractHandlerMapping handlerMapping;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
this.handlerMapping = new TestHandlerMapping();
|
||||
this.handlerMapping.setInterceptors(mock(HandlerInterceptor.class));
|
||||
this.handlerMapping.setApplicationContext(context);
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.request.setRemoteHost("domain1.com");
|
||||
@SuppressWarnings("unused")
|
||||
private static Stream<TestHandlerMapping> pathPatternsArguments() {
|
||||
return Stream.of(new TestHandlerMapping(new PathPatternParser()), new TestHandlerMapping());
|
||||
}
|
||||
|
||||
@Test
|
||||
void actualRequestWithoutCorsConfigurationProvider() throws Exception {
|
||||
this.request.setMethod(RequestMethod.GET.name());
|
||||
this.request.setRequestURI("/foo");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void actualRequestWithoutCorsConfig(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(getCorsRequest("/foo"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isInstanceOf(SimpleHandler.class);
|
||||
assertThat(mapping.hasSavedCorsConfig()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void preflightRequestWithoutCorsConfigurationProvider() throws Exception {
|
||||
this.request.setMethod(RequestMethod.OPTIONS.name());
|
||||
this.request.setRequestURI("/foo");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
@PathPatternsParameterizedTest
|
||||
void preflightRequestWithoutCorsConfig(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(getPreFlightRequest("/foo"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isNotNull();
|
||||
assertThat(chain.getHandler().getClass().getSimpleName()).isEqualTo("PreFlightHandler");
|
||||
assertThat(mapping.hasSavedCorsConfig()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void actualRequestWithCorsConfigurationProvider() throws Exception {
|
||||
this.request.setMethod(RequestMethod.GET.name());
|
||||
this.request.setRequestURI("/cors");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
@PathPatternsParameterizedTest
|
||||
void actualRequestWithCorsConfigProvider(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(getCorsRequest("/cors"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isInstanceOf(CorsAwareHandler.class);
|
||||
assertThat(getRequiredCorsConfiguration(chain, false).getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(mapping.getRequiredCorsConfig().getAllowedOrigins()).containsExactly("*");
|
||||
}
|
||||
|
||||
@Test // see gh-23843
|
||||
void actualRequestWithCorsConfigurationProviderForHandlerChain() throws Exception {
|
||||
this.request.setMethod(RequestMethod.GET.name());
|
||||
this.request.setRequestURI("/chain");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
@PathPatternsParameterizedTest // see gh-23843
|
||||
void actualRequestWithCorsConfigProviderForHandlerChain(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(getCorsRequest("/chain"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isInstanceOf(CorsAwareHandler.class);
|
||||
assertThat(getRequiredCorsConfiguration(chain, false).getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(mapping.getRequiredCorsConfig().getAllowedOrigins()).containsExactly("*");
|
||||
}
|
||||
|
||||
@Test
|
||||
void preflightRequestWithCorsConfigurationProvider() throws Exception {
|
||||
this.request.setMethod(RequestMethod.OPTIONS.name());
|
||||
this.request.setRequestURI("/cors");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
@PathPatternsParameterizedTest
|
||||
void preflightRequestWithCorsConfigProvider(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(getPreFlightRequest("/cors"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isNotNull();
|
||||
assertThat(chain.getHandler().getClass().getSimpleName()).isEqualTo("PreFlightHandler");
|
||||
assertThat(getRequiredCorsConfiguration(chain, true).getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(mapping.getRequiredCorsConfig().getAllowedOrigins()).containsExactly("*");
|
||||
}
|
||||
|
||||
@Test
|
||||
void actualRequestWithMappedCorsConfiguration() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void actualRequestWithMappedCorsConfig(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.addAllowedOrigin("*");
|
||||
this.handlerMapping.setCorsConfigurations(Collections.singletonMap("/foo", config));
|
||||
this.request.setMethod(RequestMethod.GET.name());
|
||||
this.request.setRequestURI("/foo");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
mapping.setCorsConfigurations(Collections.singletonMap("/foo", config));
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(getCorsRequest("/foo"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isInstanceOf(SimpleHandler.class);
|
||||
assertThat(getRequiredCorsConfiguration(chain, false).getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(mapping.getRequiredCorsConfig().getAllowedOrigins()).containsExactly("*");
|
||||
}
|
||||
|
||||
@Test
|
||||
void preflightRequestWithMappedCorsConfiguration() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void preflightRequestWithMappedCorsConfig(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.addAllowedOrigin("*");
|
||||
this.handlerMapping.setCorsConfigurations(Collections.singletonMap("/foo", config));
|
||||
this.request.setMethod(RequestMethod.OPTIONS.name());
|
||||
this.request.setRequestURI("/foo");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
mapping.setCorsConfigurations(Collections.singletonMap("/foo", config));
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(getPreFlightRequest("/foo"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isNotNull();
|
||||
assertThat(chain.getHandler().getClass().getSimpleName()).isEqualTo("PreFlightHandler");
|
||||
assertThat(getRequiredCorsConfiguration(chain, true).getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(mapping.getRequiredCorsConfig().getAllowedOrigins()).containsExactly("*");
|
||||
}
|
||||
|
||||
@Test
|
||||
void actualRequestWithCorsConfigurationSource() throws Exception {
|
||||
this.handlerMapping.setCorsConfigurationSource(new CustomCorsConfigurationSource());
|
||||
this.request.setMethod(RequestMethod.GET.name());
|
||||
this.request.setRequestURI("/foo");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
@PathPatternsParameterizedTest
|
||||
void actualRequestWithCorsConfigSource(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
mapping.setCorsConfigurationSource(new CustomCorsConfigurationSource());
|
||||
HandlerExecutionChain chain = mapping.getHandler(getCorsRequest("/foo"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isInstanceOf(SimpleHandler.class);
|
||||
CorsConfiguration config = getRequiredCorsConfiguration(chain, false);
|
||||
|
||||
CorsConfiguration config = mapping.getRequiredCorsConfig();
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void preflightRequestWithCorsConfigurationSource() throws Exception {
|
||||
this.handlerMapping.setCorsConfigurationSource(new CustomCorsConfigurationSource());
|
||||
this.request.setMethod(RequestMethod.OPTIONS.name());
|
||||
this.request.setRequestURI("/foo");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(this.request);
|
||||
@PathPatternsParameterizedTest
|
||||
void preflightRequestWithCorsConfigSource(TestHandlerMapping mapping) throws Exception {
|
||||
|
||||
mapping.setCorsConfigurationSource(new CustomCorsConfigurationSource());
|
||||
HandlerExecutionChain chain = mapping.getHandler(getPreFlightRequest("/foo"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler()).isNotNull();
|
||||
assertThat(chain.getHandler().getClass().getSimpleName()).isEqualTo("PreFlightHandler");
|
||||
CorsConfiguration config = getRequiredCorsConfiguration(chain, true);
|
||||
|
||||
CorsConfiguration config = mapping.getRequiredCorsConfig();
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private CorsConfiguration getRequiredCorsConfiguration(HandlerExecutionChain chain, boolean isPreFlightRequest) {
|
||||
CorsConfiguration corsConfig = null;
|
||||
if (isPreFlightRequest) {
|
||||
Object handler = chain.getHandler();
|
||||
assertThat(handler.getClass().getSimpleName()).isEqualTo("PreFlightHandler");
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(handler);
|
||||
corsConfig = (CorsConfiguration) accessor.getPropertyValue("config");
|
||||
private MockHttpServletRequest getCorsRequest(String requestURI) {
|
||||
return createCorsRequest(HttpMethod.GET, requestURI);
|
||||
}
|
||||
|
||||
private MockHttpServletRequest getPreFlightRequest(String requestURI) {
|
||||
return createCorsRequest(HttpMethod.OPTIONS, requestURI);
|
||||
}
|
||||
|
||||
private MockHttpServletRequest createCorsRequest(HttpMethod method, String requestURI) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(method.name(), requestURI);
|
||||
request.setRemoteHost("domain1.com");
|
||||
request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
private static class TestHandlerMapping extends AbstractHandlerMapping {
|
||||
|
||||
@Nullable
|
||||
private CorsConfiguration savedCorsConfig;
|
||||
|
||||
|
||||
TestHandlerMapping() {
|
||||
this(null);
|
||||
}
|
||||
else {
|
||||
HandlerInterceptor[] interceptors = chain.getInterceptors();
|
||||
if (!ObjectUtils.isEmpty(interceptors)) {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(interceptors[0]);
|
||||
corsConfig = (CorsConfiguration) accessor.getPropertyValue("config");
|
||||
|
||||
TestHandlerMapping(@Nullable PathPatternParser parser) {
|
||||
setInterceptors(mock(HandlerInterceptor.class));
|
||||
setApplicationContext(new StaticWebApplicationContext());
|
||||
if (parser != null) {
|
||||
setPatternParser(parser);
|
||||
}
|
||||
}
|
||||
assertThat(corsConfig).isNotNull();
|
||||
return corsConfig;
|
||||
}
|
||||
|
||||
public class TestHandlerMapping extends AbstractHandlerMapping {
|
||||
boolean hasSavedCorsConfig() {
|
||||
return this.savedCorsConfig != null;
|
||||
}
|
||||
|
||||
CorsConfiguration getRequiredCorsConfig() {
|
||||
assertThat(this.savedCorsConfig).isNotNull();
|
||||
return this.savedCorsConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
|
||||
if (request.getRequestURI().equals("/cors")) {
|
||||
protected Object getHandlerInternal(HttpServletRequest request) {
|
||||
String lookupPath = initLookupPath(request);
|
||||
if (lookupPath.equals("/cors")) {
|
||||
return new CorsAwareHandler();
|
||||
}
|
||||
else if (request.getRequestURI().equals("/chain")) {
|
||||
else if (lookupPath.equals("/chain")) {
|
||||
return new HandlerExecutionChain(new CorsAwareHandler());
|
||||
}
|
||||
return new SimpleHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String initLookupPath(HttpServletRequest request) {
|
||||
// At runtime this is done by the DispatcherServlet
|
||||
if (getPatternParser() != null) {
|
||||
RequestPath requestPath = ServletRequestPathUtils.parseAndCache(request);
|
||||
return requestPath.pathWithinApplication().value();
|
||||
}
|
||||
return super.initLookupPath(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HandlerExecutionChain getCorsHandlerExecutionChain(
|
||||
HttpServletRequest request, HandlerExecutionChain chain, @Nullable CorsConfiguration config) {
|
||||
|
||||
this.savedCorsConfig = config;
|
||||
return super.getCorsHandlerExecutionChain(request, chain, config);
|
||||
}
|
||||
}
|
||||
|
||||
public class SimpleHandler extends WebContentGenerator implements HttpRequestHandler {
|
||||
private static class SimpleHandler extends WebContentGenerator implements HttpRequestHandler {
|
||||
|
||||
public SimpleHandler() {
|
||||
SimpleHandler() {
|
||||
super(METHOD_GET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response) {
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CorsAwareHandler extends SimpleHandler implements CorsConfigurationSource {
|
||||
private static class CorsAwareHandler extends SimpleHandler implements CorsConfigurationSource {
|
||||
|
||||
@Override
|
||||
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
|
||||
@@ -259,7 +266,7 @@ class CorsAbstractHandlerMappingTests {
|
||||
|
||||
}
|
||||
|
||||
public class CustomCorsConfigurationSource implements CorsConfigurationSource {
|
||||
private static class CustomCorsConfigurationSource implements CorsConfigurationSource {
|
||||
|
||||
@Override
|
||||
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,8 +23,9 @@ import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -33,12 +34,16 @@ import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
@@ -53,85 +58,116 @@ import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_PATTE
|
||||
public class HandlerMappingIntrospectorTests {
|
||||
|
||||
@Test
|
||||
public void detectHandlerMappings() throws Exception {
|
||||
StaticWebApplicationContext cxt = new StaticWebApplicationContext();
|
||||
cxt.registerSingleton("hmA", SimpleUrlHandlerMapping.class);
|
||||
cxt.registerSingleton("hmB", SimpleUrlHandlerMapping.class);
|
||||
cxt.registerSingleton("hmC", SimpleUrlHandlerMapping.class);
|
||||
cxt.refresh();
|
||||
void detectHandlerMappings() {
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
context.registerSingleton("A", SimpleUrlHandlerMapping.class);
|
||||
context.registerSingleton("B", SimpleUrlHandlerMapping.class);
|
||||
context.registerSingleton("C", SimpleUrlHandlerMapping.class);
|
||||
context.refresh();
|
||||
|
||||
List<?> expected = Arrays.asList(cxt.getBean("hmA"), cxt.getBean("hmB"), cxt.getBean("hmC"));
|
||||
List<HandlerMapping> actual = getIntrospector(cxt).getHandlerMappings();
|
||||
List<?> expected = Arrays.asList(context.getBean("A"), context.getBean("B"), context.getBean("C"));
|
||||
List<HandlerMapping> actual = initIntrospector(context).getHandlerMappings();
|
||||
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectHandlerMappingsOrdered() throws Exception {
|
||||
StaticWebApplicationContext cxt = new StaticWebApplicationContext();
|
||||
MutablePropertyValues pvs = new MutablePropertyValues(Collections.singletonMap("order", "3"));
|
||||
cxt.registerSingleton("hmA", SimpleUrlHandlerMapping.class, pvs);
|
||||
pvs = new MutablePropertyValues(Collections.singletonMap("order", "2"));
|
||||
cxt.registerSingleton("hmB", SimpleUrlHandlerMapping.class, pvs);
|
||||
pvs = new MutablePropertyValues(Collections.singletonMap("order", "1"));
|
||||
cxt.registerSingleton("hmC", SimpleUrlHandlerMapping.class, pvs);
|
||||
cxt.refresh();
|
||||
void detectHandlerMappingsOrdered() {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
context.registerBean("B", SimpleUrlHandlerMapping.class, () -> {
|
||||
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
|
||||
mapping.setOrder(2);
|
||||
return mapping;
|
||||
});
|
||||
context.registerBean("C", SimpleUrlHandlerMapping.class, () -> {
|
||||
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
|
||||
mapping.setOrder(3);
|
||||
return mapping;
|
||||
});
|
||||
context.registerBean("A", SimpleUrlHandlerMapping.class, () -> {
|
||||
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
|
||||
mapping.setOrder(1);
|
||||
return mapping;
|
||||
});
|
||||
context.refresh();
|
||||
|
||||
List<?> expected = Arrays.asList(cxt.getBean("hmC"), cxt.getBean("hmB"), cxt.getBean("hmA"));
|
||||
List<HandlerMapping> actual = getIntrospector(cxt).getHandlerMappings();
|
||||
List<?> expected = Arrays.asList(context.getBean("A"), context.getBean("B"), context.getBean("C"));
|
||||
List<HandlerMapping> actual = initIntrospector(context).getHandlerMappings();
|
||||
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
public void defaultHandlerMappings() throws Exception {
|
||||
StaticWebApplicationContext cxt = new StaticWebApplicationContext();
|
||||
cxt.refresh();
|
||||
void defaultHandlerMappings() {
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
context.refresh();
|
||||
List<HandlerMapping> actual = initIntrospector(context).getHandlerMappings();
|
||||
|
||||
List<HandlerMapping> actual = getIntrospector(cxt).getHandlerMappings();
|
||||
assertThat(actual.size()).isEqualTo(2);
|
||||
assertThat(actual.get(0).getClass()).isEqualTo(BeanNameUrlHandlerMapping.class);
|
||||
assertThat(actual.get(1).getClass()).isEqualTo(RequestMappingHandlerMapping.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMatchable() throws Exception {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues(
|
||||
Collections.singletonMap("urlMap", Collections.singletonMap("/path", new Object())));
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
void getMatchable(boolean usePathPatterns) throws Exception {
|
||||
|
||||
StaticWebApplicationContext cxt = new StaticWebApplicationContext();
|
||||
cxt.registerSingleton("hm", SimpleUrlHandlerMapping.class, pvs);
|
||||
cxt.refresh();
|
||||
PathPatternParser parser = new PathPatternParser();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/path");
|
||||
MatchableHandlerMapping hm = getIntrospector(cxt).getMatchableHandlerMapping(request);
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
context.registerBean("mapping", SimpleUrlHandlerMapping.class, () -> {
|
||||
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
|
||||
if (usePathPatterns) {
|
||||
mapping.setPatternParser(parser);
|
||||
}
|
||||
mapping.setUrlMap(Collections.singletonMap("/path/*", new Object()));
|
||||
return mapping;
|
||||
});
|
||||
context.refresh();
|
||||
|
||||
assertThat(hm).isEqualTo(cxt.getBean("hm"));
|
||||
assertThat(request.getAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE)).as("Attributes changes not ignored").isNull();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/path/123");
|
||||
|
||||
// Initialize the RequestPath. At runtime, ServletRequestPathFilter is expected to do that.
|
||||
if (usePathPatterns) {
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
}
|
||||
|
||||
MatchableHandlerMapping mapping = initIntrospector(context).getMatchableHandlerMapping(request);
|
||||
|
||||
assertThat(mapping).isNotNull();
|
||||
assertThat(mapping).isEqualTo(context.getBean("mapping"));
|
||||
assertThat(request.getAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE)).as("Attribute changes not ignored").isNull();
|
||||
|
||||
String pattern = "/p*/*";
|
||||
PathPattern pathPattern = parser.parse(pattern);
|
||||
assertThat(usePathPatterns ? mapping.match(request, pathPattern) : mapping.match(request, pattern)).isNotNull();
|
||||
|
||||
pattern = "/b*/*";
|
||||
pathPattern = parser.parse(pattern);
|
||||
assertThat(usePathPatterns ? mapping.match(request, pathPattern) : mapping.match(request, pattern)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMatchableWhereHandlerMappingDoesNotImplementMatchableInterface() throws Exception {
|
||||
void getMatchableWhereHandlerMappingDoesNotImplementMatchableInterface() {
|
||||
StaticWebApplicationContext cxt = new StaticWebApplicationContext();
|
||||
cxt.registerSingleton("hm1", TestHandlerMapping.class);
|
||||
cxt.registerSingleton("mapping", TestHandlerMapping.class);
|
||||
cxt.refresh();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
assertThatIllegalStateException().isThrownBy(() ->
|
||||
getIntrospector(cxt).getMatchableHandlerMapping(request));
|
||||
assertThatIllegalStateException().isThrownBy(() -> initIntrospector(cxt).getMatchableHandlerMapping(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCorsConfigurationPreFlight() throws Exception {
|
||||
AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext();
|
||||
cxt.register(TestConfig.class);
|
||||
cxt.refresh();
|
||||
void getCorsConfigurationPreFlight() {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(TestConfig.class);
|
||||
context.refresh();
|
||||
|
||||
// PRE-FLIGHT
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/path");
|
||||
request.addHeader("Origin", "http://localhost:9000");
|
||||
request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST");
|
||||
CorsConfiguration corsConfig = getIntrospector(cxt).getCorsConfiguration(request);
|
||||
CorsConfiguration corsConfig = initIntrospector(context).getCorsConfiguration(request);
|
||||
|
||||
assertThat(corsConfig).isNotNull();
|
||||
assertThat(corsConfig.getAllowedOrigins()).isEqualTo(Collections.singletonList("http://localhost:9000"));
|
||||
@@ -139,23 +175,23 @@ public class HandlerMappingIntrospectorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCorsConfigurationActual() throws Exception {
|
||||
AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext();
|
||||
cxt.register(TestConfig.class);
|
||||
cxt.refresh();
|
||||
void getCorsConfigurationActual() {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(TestConfig.class);
|
||||
context.refresh();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/path");
|
||||
request.addHeader("Origin", "http://localhost:9000");
|
||||
CorsConfiguration corsConfig = getIntrospector(cxt).getCorsConfiguration(request);
|
||||
CorsConfiguration corsConfig = initIntrospector(context).getCorsConfiguration(request);
|
||||
|
||||
assertThat(corsConfig).isNotNull();
|
||||
assertThat(corsConfig.getAllowedOrigins()).isEqualTo(Collections.singletonList("http://localhost:9000"));
|
||||
assertThat(corsConfig.getAllowedMethods()).isEqualTo(Collections.singletonList("POST"));
|
||||
}
|
||||
|
||||
private HandlerMappingIntrospector getIntrospector(WebApplicationContext cxt) {
|
||||
private HandlerMappingIntrospector initIntrospector(WebApplicationContext context) {
|
||||
HandlerMappingIntrospector introspector = new HandlerMappingIntrospector();
|
||||
introspector.setApplicationContext(cxt);
|
||||
introspector.setApplicationContext(context);
|
||||
introspector.afterPropertiesSet();
|
||||
return introspector;
|
||||
}
|
||||
@@ -164,14 +200,13 @@ public class HandlerMappingIntrospectorTests {
|
||||
private static class TestHandlerMapping implements HandlerMapping {
|
||||
|
||||
@Override
|
||||
public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
|
||||
public HandlerExecutionChain getHandler(HttpServletRequest request) {
|
||||
return new HandlerExecutionChain(new Object());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
@@ -191,7 +226,7 @@ public class HandlerMappingIntrospectorTests {
|
||||
private static class TestController {
|
||||
|
||||
@PostMapping("/path")
|
||||
public void handle() {
|
||||
void handle() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,20 +16,18 @@
|
||||
|
||||
package org.springframework.web.servlet.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.support.WebContentGenerator;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -38,49 +36,51 @@ import static org.mockito.Mockito.mock;
|
||||
/**
|
||||
* Unit tests for {@link org.springframework.web.servlet.HandlerMapping}.
|
||||
* @author Brian Clozel
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class HandlerMappingTests {
|
||||
class HandlerMappingTests {
|
||||
|
||||
private AbstractHandlerMapping handlerMapping = new TestHandlerMapping();
|
||||
private StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
private MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
@SuppressWarnings("unused")
|
||||
private static Stream<Arguments> pathPatternsArguments() {
|
||||
List<Function<String, MockHttpServletRequest>> factories =
|
||||
PathPatternsTestUtils.requestArguments().collect(Collectors.toList());
|
||||
return Stream.of(
|
||||
Arguments.arguments(new TestHandlerMapping(), factories.get(0)),
|
||||
Arguments.arguments(new TestHandlerMapping(), factories.get(1))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void orderedInterceptors() throws Exception {
|
||||
HandlerInterceptor i1 = mock(HandlerInterceptor.class);
|
||||
MappedInterceptor mappedInterceptor1 = new MappedInterceptor(new String[]{"/**"}, i1);
|
||||
@PathPatternsParameterizedTest
|
||||
void orderedInterceptors(
|
||||
TestHandlerMapping mapping, Function<String, MockHttpServletRequest> requestFactory)
|
||||
throws Exception {
|
||||
|
||||
MappedInterceptor i1 = new MappedInterceptor(new String[] {"/**"}, mock(HandlerInterceptor.class));
|
||||
HandlerInterceptor i2 = mock(HandlerInterceptor.class);
|
||||
HandlerInterceptor i3 = mock(HandlerInterceptor.class);
|
||||
MappedInterceptor mappedInterceptor3 = new MappedInterceptor(new String[]{"/**"}, i3);
|
||||
MappedInterceptor i3 = new MappedInterceptor(new String[] {"/**"}, mock(HandlerInterceptor.class));
|
||||
HandlerInterceptor i4 = mock(HandlerInterceptor.class);
|
||||
|
||||
this.handlerMapping.setInterceptors(mappedInterceptor1, i2, mappedInterceptor3, i4);
|
||||
this.handlerMapping.setApplicationContext(this.context);
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandlerExecutionChain(new SimpleHandler(), this.request);
|
||||
assertThat(chain.getInterceptors()).contains(
|
||||
mappedInterceptor1.getInterceptor(), i2, mappedInterceptor3.getInterceptor(), i4);
|
||||
mapping.setInterceptors(i1, i2, i3, i4);
|
||||
mapping.setApplicationContext(new StaticWebApplicationContext());
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(requestFactory.apply("/"));
|
||||
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getInterceptors()).contains(i1.getInterceptor(), i2, i3.getInterceptor(), i4);
|
||||
}
|
||||
|
||||
class TestHandlerMapping extends AbstractHandlerMapping {
|
||||
|
||||
@Override
|
||||
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
|
||||
return new SimpleHandler();
|
||||
}
|
||||
}
|
||||
private static class TestHandlerMapping extends AbstractHandlerMapping {
|
||||
|
||||
class SimpleHandler extends WebContentGenerator implements HttpRequestHandler {
|
||||
|
||||
public SimpleHandler() {
|
||||
super(METHOD_GET);
|
||||
TestHandlerMapping() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
protected Object getHandlerInternal(HttpServletRequest request) {
|
||||
initLookupPath(request);
|
||||
return new Object();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -17,18 +17,19 @@ package org.springframework.web.servlet.handler;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -37,96 +38,95 @@ import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link MappedInterceptor} tests.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class MappedInterceptorTests {
|
||||
class MappedInterceptorTests {
|
||||
|
||||
private LocaleChangeInterceptor interceptor;
|
||||
private static final LocaleChangeInterceptor delegate = new LocaleChangeInterceptor();
|
||||
|
||||
private final AntPathMatcher pathMatcher = new AntPathMatcher();
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
this.interceptor = new LocaleChangeInterceptor();
|
||||
@SuppressWarnings("unused")
|
||||
private static Stream<Function<String, MockHttpServletRequest>> pathPatternsArguments() {
|
||||
return PathPatternsTestUtils.requestArguments();
|
||||
}
|
||||
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void noPatterns(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MappedInterceptor interceptor = new MappedInterceptor(null, null, delegate);
|
||||
assertThat(interceptor.matches(requestFactory.apply("/foo"))).isTrue();
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void includePattern(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MappedInterceptor interceptor = new MappedInterceptor(new String[] { "/foo/*" }, null, delegate);
|
||||
|
||||
assertThat(interceptor.matches(requestFactory.apply("/foo/bar"))).isTrue();
|
||||
assertThat(interceptor.matches(requestFactory.apply("/bar/foo"))).isFalse();
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void includePatternWithMatrixVariables(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MappedInterceptor interceptor = new MappedInterceptor(new String[] { "/foo*/*" }, null, delegate);
|
||||
assertThat(interceptor.matches(requestFactory.apply("/foo;q=1/bar;s=2"))).isTrue();
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void excludePattern(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MappedInterceptor interceptor = new MappedInterceptor(null, new String[] { "/admin/**" }, delegate);
|
||||
|
||||
assertThat(interceptor.matches(requestFactory.apply("/foo"))).isTrue();
|
||||
assertThat(interceptor.matches(requestFactory.apply("/admin/foo"))).isFalse();
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void includeAndExcludePatterns(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MappedInterceptor interceptor =
|
||||
new MappedInterceptor(new String[] { "/**" }, new String[] { "/admin/**" }, delegate);
|
||||
|
||||
assertThat(interceptor.matches(requestFactory.apply("/foo"))).isTrue();
|
||||
assertThat(interceptor.matches(requestFactory.apply("/admin/foo"))).isFalse();
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void customPathMatcher(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MappedInterceptor interceptor = new MappedInterceptor(new String[] { "/foo/[0-9]*" }, null, delegate);
|
||||
interceptor.setPathMatcher(new TestPathMatcher());
|
||||
|
||||
assertThat(interceptor.matches(requestFactory.apply("/foo/123"))).isTrue();
|
||||
assertThat(interceptor.matches(requestFactory.apply("/foo/bar"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noPatterns() {
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(null, null, this.interceptor);
|
||||
assertThat(mappedInterceptor.matches("/foo", pathMatcher)).isTrue();
|
||||
void preHandle() throws Exception {
|
||||
HandlerInterceptor delegate = mock(HandlerInterceptor.class);
|
||||
|
||||
new MappedInterceptor(null, delegate).preHandle(
|
||||
mock(HttpServletRequest.class), mock(HttpServletResponse.class), null);
|
||||
|
||||
then(delegate).should().preHandle(any(HttpServletRequest.class), any(HttpServletResponse.class), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includePattern() {
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[] { "/foo/*" }, this.interceptor);
|
||||
void postHandle() throws Exception {
|
||||
HandlerInterceptor delegate = mock(HandlerInterceptor.class);
|
||||
|
||||
assertThat(mappedInterceptor.matches("/foo/bar", pathMatcher)).isTrue();
|
||||
assertThat(mappedInterceptor.matches("/bar/foo", pathMatcher)).isFalse();
|
||||
new MappedInterceptor(null, delegate).postHandle(
|
||||
mock(HttpServletRequest.class), mock(HttpServletResponse.class), null, mock(ModelAndView.class));
|
||||
|
||||
then(delegate).should().postHandle(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includePatternWithMatrixVariables() {
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[] { "/foo*/*" }, this.interceptor);
|
||||
assertThat(mappedInterceptor.matches("/foo;q=1/bar;s=2", pathMatcher)).isTrue();
|
||||
void afterCompletion() throws Exception {
|
||||
HandlerInterceptor delegate = mock(HandlerInterceptor.class);
|
||||
|
||||
new MappedInterceptor(null, delegate).afterCompletion(
|
||||
mock(HttpServletRequest.class), mock(HttpServletResponse.class), null, mock(Exception.class));
|
||||
|
||||
then(delegate).should().afterCompletion(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void excludePattern() {
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(null, new String[] { "/admin/**" }, this.interceptor);
|
||||
|
||||
assertThat(mappedInterceptor.matches("/foo", pathMatcher)).isTrue();
|
||||
assertThat(mappedInterceptor.matches("/admin/foo", pathMatcher)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeAndExcludePatterns() {
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(
|
||||
new String[] { "/**" }, new String[] { "/admin/**" }, this.interceptor);
|
||||
|
||||
assertThat(mappedInterceptor.matches("/foo", pathMatcher)).isTrue();
|
||||
assertThat(mappedInterceptor.matches("/admin/foo", pathMatcher)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customPathMatcher() {
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[] { "/foo/[0-9]*" }, this.interceptor);
|
||||
mappedInterceptor.setPathMatcher(new TestPathMatcher());
|
||||
|
||||
assertThat(mappedInterceptor.matches("/foo/123", pathMatcher)).isTrue();
|
||||
assertThat(mappedInterceptor.matches("/foo/bar", pathMatcher)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandle() throws Exception {
|
||||
HandlerInterceptor interceptor = mock(HandlerInterceptor.class);
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[] { "/**" }, interceptor);
|
||||
mappedInterceptor.preHandle(mock(HttpServletRequest.class), mock(HttpServletResponse.class), null);
|
||||
|
||||
then(interceptor).should().preHandle(any(HttpServletRequest.class), any(HttpServletResponse.class), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postHandle() throws Exception {
|
||||
HandlerInterceptor interceptor = mock(HandlerInterceptor.class);
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[] { "/**" }, interceptor);
|
||||
mappedInterceptor.postHandle(mock(HttpServletRequest.class), mock(HttpServletResponse.class),
|
||||
null, mock(ModelAndView.class));
|
||||
|
||||
then(interceptor).should().postHandle(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterCompletion() throws Exception {
|
||||
HandlerInterceptor interceptor = mock(HandlerInterceptor.class);
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[] { "/**" }, interceptor);
|
||||
mappedInterceptor.afterCompletion(mock(HttpServletRequest.class), mock(HttpServletResponse.class),
|
||||
null, mock(Exception.class));
|
||||
|
||||
then(interceptor).should().afterCompletion(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class TestPathMatcher implements PathMatcher {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,16 +16,19 @@
|
||||
|
||||
package org.springframework.web.servlet.handler;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.XmlWebApplicationContext;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -35,41 +38,49 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class PathMatchingUrlHandlerMappingTests {
|
||||
|
||||
public static final String CONF = "/org/springframework/web/servlet/handler/map3.xml";
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<?> pathPatternsArguments() {
|
||||
String location = "/org/springframework/web/servlet/handler/map3.xml";
|
||||
WebApplicationContext wac = initConfig(location);
|
||||
|
||||
private HandlerMapping hm;
|
||||
SimpleUrlHandlerMapping mapping1 = wac.getBean("urlMapping1", SimpleUrlHandlerMapping.class);
|
||||
assertThat(mapping1.getPathPatternHandlerMap()).isNotEmpty();
|
||||
|
||||
private ConfigurableWebApplicationContext wac;
|
||||
SimpleUrlHandlerMapping mapping2 = wac.getBean("urlMapping2", SimpleUrlHandlerMapping.class);
|
||||
assertThat(mapping2.getPathPatternHandlerMap()).isEmpty();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
MockServletContext sc = new MockServletContext("");
|
||||
wac = new XmlWebApplicationContext();
|
||||
wac.setServletContext(sc);
|
||||
wac.setConfigLocations(new String[] {CONF});
|
||||
wac.refresh();
|
||||
hm = (HandlerMapping) wac.getBean("urlMapping");
|
||||
return Stream.of(Arguments.of(mapping1, wac), Arguments.of(mapping2, wac));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestsWithHandlers() throws Exception {
|
||||
private static WebApplicationContext initConfig(String... configLocations) {
|
||||
MockServletContext sc = new MockServletContext("");
|
||||
ConfigurableWebApplicationContext context = new XmlWebApplicationContext();
|
||||
context.setServletContext(sc);
|
||||
context.setConfigLocations(configLocations);
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void requestsWithHandlers(HandlerMapping mapping, WebApplicationContext wac) throws Exception {
|
||||
Object bean = wac.getBean("mainController");
|
||||
|
||||
MockHttpServletRequest req = new MockHttpServletRequest("GET", "/welcome.html");
|
||||
HandlerExecutionChain hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
HandlerExecutionChain hec = getHandler(mapping, wac, req);
|
||||
assertThat(hec.getHandler() == bean).isTrue();
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/show.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
hec = getHandler(mapping, wac, req);
|
||||
assertThat(hec.getHandler() == bean).isTrue();
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/bookseats.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
hec = getHandler(mapping, wac, req);
|
||||
assertThat(hec.getHandler() == bean).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actualPathMatching() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void actualPathMatching(SimpleUrlHandlerMapping mapping, WebApplicationContext wac) throws Exception {
|
||||
// there a couple of mappings defined with which we can test the
|
||||
// path matching, let's do that...
|
||||
|
||||
@@ -77,178 +88,199 @@ public class PathMatchingUrlHandlerMappingTests {
|
||||
Object defaultBean = wac.getBean("starController");
|
||||
|
||||
// testing some normal behavior
|
||||
MockHttpServletRequest req = new MockHttpServletRequest("GET", "/pathmatchingTest.html");
|
||||
HandlerExecutionChain hec = getHandler(req);
|
||||
assertThat(hec != null).as("Handler is null").isTrue();
|
||||
assertThat(hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("/pathmatchingTest.html");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/pathmatchingTest.html");
|
||||
HandlerExecutionChain chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
assertThat(request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE))
|
||||
.isEqualTo("/pathmatchingTest.html");
|
||||
|
||||
// no match, no forward slash included
|
||||
req = new MockHttpServletRequest("GET", "welcome.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("welcome.html");
|
||||
request = new MockHttpServletRequest("GET", "welcome.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
assertThat(request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE))
|
||||
.isEqualTo("welcome.html");
|
||||
|
||||
// testing some ????? behavior
|
||||
req = new MockHttpServletRequest("GET", "/pathmatchingAA.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("pathmatchingAA.html");
|
||||
request = new MockHttpServletRequest("GET", "/pathmatchingAA.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
assertThat(request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE))
|
||||
.isEqualTo("pathmatchingAA.html");
|
||||
|
||||
// testing some ????? behavior
|
||||
req = new MockHttpServletRequest("GET", "/pathmatchingA.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("/pathmatchingA.html");
|
||||
request = new MockHttpServletRequest("GET", "/pathmatchingA.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
assertThat(request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE))
|
||||
.isEqualTo("/pathmatchingA.html");
|
||||
|
||||
// testing some ????? behavior
|
||||
req = new MockHttpServletRequest("GET", "/administrator/pathmatching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/pathmatching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
// testing simple /**/behavior
|
||||
req = new MockHttpServletRequest("GET", "/administrator/test/pathmatching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/test/pathmatching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
// this should not match because of the administratorT
|
||||
req = new MockHttpServletRequest("GET", "/administratort/pathmatching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administratort/pathmatching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
// this should match because of *.jsp
|
||||
req = new MockHttpServletRequest("GET", "/bla.jsp");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/bla.jsp");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
// should match because exact pattern is there
|
||||
req = new MockHttpServletRequest("GET", "/administrator/another/bla.xml");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/another/bla.xml");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
// should not match, because there's not .gif extension in there
|
||||
req = new MockHttpServletRequest("GET", "/administrator/another/bla.gif");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/another/bla.gif");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
// should match because there testlast* in there
|
||||
req = new MockHttpServletRequest("GET", "/administrator/test/testlastbit");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/test/testlastbit");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
// but this not, because it's testlast and not testla
|
||||
req = new MockHttpServletRequest("GET", "/administrator/test/testla");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/test/testla");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/administrator/testing/longer/bla");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/testing/longer/bla");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/administrator/testing/longer/test.jsp");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/testing/longer/test.jsp");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/administrator/testing/longer2/notmatching/notmatching");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/administrator/testing/longer2/notmatching/notmatching");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/shortpattern/testing/toolong");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/shortpattern/testing/toolong");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/XXpathXXmatching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/XXpathXXmatching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/pathXXmatching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/pathXXmatching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/XpathXXmatching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/XpathXXmatching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/XXpathmatching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/XXpathmatching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/show12.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/show12.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/show123.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/show123.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/show1.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/show1.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/reallyGood-test-is-this.jpeg");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/reallyGood-test-is-this.jpeg");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/reallyGood-tst-is-this.jpeg");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/reallyGood-tst-is-this.jpeg");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/testing/test.jpeg");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/testing/test.jpeg");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/testing/test.jpg");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/testing/test.jpg");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/anotherTest");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/anotherTest");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/stillAnotherTest");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/stillAnotherTest");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
// there outofpattern*yeah in the pattern, so this should fail
|
||||
req = new MockHttpServletRequest("GET", "/outofpattern*ye");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/outofpattern*ye");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/test't est/path'm atching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/test't%20est/path'm%20atching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
assertThat(chain.getHandler()).isSameAs(defaultBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/test%26t%20est/path%26m%20atching.html");
|
||||
hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
request = new MockHttpServletRequest("GET", "/test%26t%20est/path%26m%20atching.html");
|
||||
chain = getHandler(mapping, wac, request);
|
||||
if (!mapping.getPathPatternHandlerMap().isEmpty()) {
|
||||
assertThat(chain.getHandler())
|
||||
.as("PathPattern always matches to encoded paths.")
|
||||
.isSameAs(bean);
|
||||
}
|
||||
else {
|
||||
assertThat(chain.getHandler())
|
||||
.as("PathMatcher should not match encoded pattern with urlDecode=true")
|
||||
.isSameAs(defaultBean);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMapping() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void defaultMapping(HandlerMapping mapping, WebApplicationContext wac) throws Exception {
|
||||
Object bean = wac.getBean("starController");
|
||||
MockHttpServletRequest req = new MockHttpServletRequest("GET", "/goggog.html");
|
||||
HandlerExecutionChain hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
HandlerExecutionChain hec = getHandler(mapping, wac, req);
|
||||
assertThat(hec.getHandler()).isSameAs(bean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingExposedInRequest() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void mappingExposedInRequest(HandlerMapping mapping, WebApplicationContext wac) throws Exception {
|
||||
Object bean = wac.getBean("mainController");
|
||||
MockHttpServletRequest req = new MockHttpServletRequest("GET", "/show.html");
|
||||
HandlerExecutionChain hec = getHandler(req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).as("Mapping not exposed").isEqualTo("show.html");
|
||||
HandlerExecutionChain hec = getHandler(mapping, wac, req);
|
||||
assertThat(hec.getHandler()).isSameAs(bean);
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE))
|
||||
.as("Mapping not exposed").isEqualTo("show.html");
|
||||
}
|
||||
|
||||
private HandlerExecutionChain getHandler(MockHttpServletRequest req) throws Exception {
|
||||
HandlerExecutionChain hec = hm.getHandler(req);
|
||||
HandlerInterceptor[] interceptors = hec.getInterceptors();
|
||||
private HandlerExecutionChain getHandler(
|
||||
HandlerMapping mapping, WebApplicationContext wac, MockHttpServletRequest request)
|
||||
throws Exception {
|
||||
|
||||
// At runtime this is done by the DispatcherServlet
|
||||
if (((AbstractHandlerMapping) mapping).getPatternParser() != null) {
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
}
|
||||
|
||||
HandlerExecutionChain executionChain = mapping.getHandler(request);
|
||||
HandlerInterceptor[] interceptors = executionChain.getInterceptors();
|
||||
if (interceptors != null) {
|
||||
for (HandlerInterceptor interceptor : interceptors) {
|
||||
interceptor.preHandle(req, null, hec.getHandler());
|
||||
interceptor.preHandle(request, null, executionChain.getHandler());
|
||||
}
|
||||
}
|
||||
return hec;
|
||||
return executionChain;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.web.servlet.handler;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation for tests parameterized to use either
|
||||
* {@link org.springframework.web.util.pattern.PathPatternParser} or
|
||||
* {@link org.springframework.util.PathMatcher} for URL pattern matching.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.3
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@org.junit.jupiter.params.ParameterizedTest
|
||||
@org.junit.jupiter.params.provider.MethodSource("pathPatternsArguments")
|
||||
public @interface PathPatternsParameterizedTest {
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.web.servlet.handler;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
* Utility methods to help with parameterized tests for URL pattern matching
|
||||
* via pre-parsed {@code PathPattern}s or String pattern matching with
|
||||
* {@code PathMatcher}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.3
|
||||
*/
|
||||
public abstract class PathPatternsTestUtils {
|
||||
|
||||
public static Stream<Function<String, MockHttpServletRequest>> requestArguments() {
|
||||
return requestArguments(null);
|
||||
}
|
||||
|
||||
public static Stream<Function<String, MockHttpServletRequest>> requestArguments(@Nullable String contextPath) {
|
||||
return Stream.of(
|
||||
path -> {
|
||||
MockHttpServletRequest request = createRequest("GET", contextPath, path);
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
return request;
|
||||
},
|
||||
path -> {
|
||||
MockHttpServletRequest request = createRequest("GET", contextPath, path);
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
return request;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MockHttpServletRequest and initialize the request attributes for
|
||||
* the lookupPath via {@link ServletRequestPathUtils} or {@link UrlPathHelper}
|
||||
* depending on the setting of the parsedPatterns argument.
|
||||
* <p>At runtime this would be done by the DispatcherServlet (for the RequestPath)
|
||||
* and by the AbstractHandlerMapping (for UrlPathHelper).
|
||||
*/
|
||||
public static MockHttpServletRequest initRequest(String method, String requestUri, boolean parsedPatterns) {
|
||||
return initRequest(method, null, requestUri, parsedPatterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #initRequest(String, String, boolean)}. This variant adds a contextPath.
|
||||
*/
|
||||
public static MockHttpServletRequest initRequest(
|
||||
String method, @Nullable String contextPath, String path, boolean parsedPatterns) {
|
||||
|
||||
return initRequest(method, contextPath, path, parsedPatterns, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #initRequest(String, String, boolean)}. This variant adds a contextPath
|
||||
* and a post-construct initializer to apply further changes before the
|
||||
* lookupPath is resolved.
|
||||
*/
|
||||
public static MockHttpServletRequest initRequest(
|
||||
String method, @Nullable String contextPath, String path,
|
||||
boolean parsedPatterns, @Nullable Consumer<MockHttpServletRequest> postConstructInitializer) {
|
||||
|
||||
MockHttpServletRequest request = createRequest(method, contextPath, path);
|
||||
if (postConstructInitializer != null) {
|
||||
postConstructInitializer.accept(request);
|
||||
}
|
||||
// At runtime this is done by the DispatcherServlet and AbstractHandlerMapping
|
||||
if (parsedPatterns) {
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
}
|
||||
else {
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private static MockHttpServletRequest createRequest(String method, @Nullable String contextPath, String path) {
|
||||
if (contextPath != null) {
|
||||
String requestUri = contextPath + (path.startsWith("/") ? "" : "/") + path;
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(method, requestUri);
|
||||
request.setContextPath(contextPath);
|
||||
return request;
|
||||
}
|
||||
else {
|
||||
return new MockHttpServletRequest(method, path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -19,6 +19,8 @@ package org.springframework.web.servlet.handler;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
@@ -33,6 +35,8 @@ import org.springframework.web.util.WebUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE;
|
||||
import static org.springframework.web.servlet.HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
@@ -48,44 +52,38 @@ public class SimpleUrlHandlerMappingTests {
|
||||
root.setServletContext(sc);
|
||||
root.setConfigLocations("/org/springframework/web/servlet/handler/map1.xml");
|
||||
root.refresh();
|
||||
|
||||
XmlWebApplicationContext wac = new XmlWebApplicationContext();
|
||||
wac.setParent(root);
|
||||
wac.setServletContext(sc);
|
||||
wac.setNamespace("map2err");
|
||||
wac.setConfigLocations("/org/springframework/web/servlet/handler/map2err.xml");
|
||||
assertThatExceptionOfType(FatalBeanException.class).isThrownBy(
|
||||
wac::refresh)
|
||||
.withCauseInstanceOf(NoSuchBeanDefinitionException.class)
|
||||
.satisfies(ex -> assertThat(((NoSuchBeanDefinitionException) ex.getCause()).getBeanName()).isEqualTo("mainControlle"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMappingWithUrlMap() throws Exception {
|
||||
checkMappings("urlMapping");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMappingWithProps() throws Exception {
|
||||
checkMappings("urlMappingWithProps");
|
||||
assertThatExceptionOfType(FatalBeanException.class)
|
||||
.isThrownBy(wac::refresh)
|
||||
.withCauseInstanceOf(NoSuchBeanDefinitionException.class)
|
||||
.satisfies(ex -> {
|
||||
NoSuchBeanDefinitionException cause = (NoSuchBeanDefinitionException) ex.getCause();
|
||||
assertThat(cause.getBeanName()).isEqualTo("mainControlle");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewlineInRequest() throws Exception {
|
||||
Object controller = new Object();
|
||||
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(
|
||||
Collections.singletonMap("/*/baz", controller));
|
||||
handlerMapping.setUrlDecode(false);
|
||||
handlerMapping.setApplicationContext(new StaticApplicationContext());
|
||||
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(Collections.singletonMap("/*/baz", controller));
|
||||
mapping.setUrlDecode(false);
|
||||
mapping.setApplicationContext(new StaticApplicationContext());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo%0a%0dbar/baz");
|
||||
|
||||
HandlerExecutionChain hec = handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain hec = mapping.getHandler(request);
|
||||
assertThat(hec).isNotNull();
|
||||
assertThat(hec.getHandler()).isSameAs(controller);
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
private void checkMappings(String beanName) throws Exception {
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"urlMapping", "urlMappingWithProps", "urlMappingWithPathPatterns"})
|
||||
void checkMappings(String beanName) throws Exception {
|
||||
MockServletContext sc = new MockServletContext("");
|
||||
XmlWebApplicationContext wac = new XmlWebApplicationContext();
|
||||
wac.setServletContext(sc);
|
||||
@@ -96,76 +94,76 @@ public class SimpleUrlHandlerMappingTests {
|
||||
Object defaultBean = wac.getBean("starController");
|
||||
HandlerMapping hm = (HandlerMapping) wac.getBean(beanName);
|
||||
|
||||
MockHttpServletRequest req = new MockHttpServletRequest("GET", "/welcome.html");
|
||||
HandlerExecutionChain hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("/welcome.html");
|
||||
assertThat(req.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE)).isEqualTo(bean);
|
||||
boolean usePathPatterns = (((AbstractHandlerMapping) hm).getPatternParser() != null);
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/welcome.html", usePathPatterns);
|
||||
HandlerExecutionChain chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
assertThat(request.getAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("/welcome.html");
|
||||
assertThat(request.getAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE)).isEqualTo(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/welcome.x");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == otherBean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("welcome.x");
|
||||
assertThat(req.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE)).isEqualTo(otherBean);
|
||||
request = PathPatternsTestUtils.initRequest("GET", "/welcome.x", usePathPatterns);
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(otherBean);
|
||||
assertThat(request.getAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("welcome.x");
|
||||
assertThat(request.getAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE)).isEqualTo(otherBean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/welcome/");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == otherBean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("welcome");
|
||||
request = PathPatternsTestUtils.initRequest("GET", "/welcome/", usePathPatterns);
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(otherBean);
|
||||
assertThat(request.getAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("welcome");
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/");
|
||||
req.setServletPath("/welcome.html");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = PathPatternsTestUtils.initRequest("GET", "/", usePathPatterns);
|
||||
request.setServletPath("/welcome.html");
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/welcome.html");
|
||||
req.setContextPath("/app");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = PathPatternsTestUtils.initRequest("GET", "/app", "/welcome.html", usePathPatterns);
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/show.html");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = PathPatternsTestUtils.initRequest("GET", "/show.html", usePathPatterns);
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/bookseats.html");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = PathPatternsTestUtils.initRequest("GET", "/bookseats.html", usePathPatterns);
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/original-welcome.html");
|
||||
req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/welcome.html");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = PathPatternsTestUtils.initRequest("GET", null, "/original-welcome.html", usePathPatterns,
|
||||
req -> req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/welcome.html"));
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/original-show.html");
|
||||
req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/show.html");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = PathPatternsTestUtils.initRequest("GET", null, "/original-show.html", usePathPatterns,
|
||||
req -> req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/show.html"));
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/original-bookseats.html");
|
||||
req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/bookseats.html");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
request = PathPatternsTestUtils.initRequest("GET", null, "/original-bookseats.html", usePathPatterns,
|
||||
req -> req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/bookseats.html"));
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == bean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("/");
|
||||
request = PathPatternsTestUtils.initRequest("GET", "/", usePathPatterns);
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler()).isSameAs(bean);
|
||||
assertThat(request.getAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("/");
|
||||
|
||||
req = new MockHttpServletRequest("GET", "/somePath");
|
||||
hec = getHandler(hm, req);
|
||||
assertThat(hec != null && hec.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
assertThat(req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("/somePath");
|
||||
request = PathPatternsTestUtils.initRequest("GET", "/somePath", usePathPatterns);
|
||||
chain = getHandler(hm, request);
|
||||
assertThat(chain.getHandler() == defaultBean).as("Handler is correct bean").isTrue();
|
||||
assertThat(request.getAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).isEqualTo("/somePath");
|
||||
}
|
||||
|
||||
private HandlerExecutionChain getHandler(HandlerMapping hm, MockHttpServletRequest req) throws Exception {
|
||||
HandlerExecutionChain hec = hm.getHandler(req);
|
||||
HandlerInterceptor[] interceptors = hec.getInterceptors();
|
||||
private HandlerExecutionChain getHandler(HandlerMapping mapping, MockHttpServletRequest request) throws Exception {
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
HandlerInterceptor[] interceptors = chain.getInterceptors();
|
||||
if (interceptors != null) {
|
||||
for (HandlerInterceptor interceptor : interceptors) {
|
||||
interceptor.preHandle(req, null, hec.getHandler());
|
||||
interceptor.preHandle(request, null, chain.getHandler());
|
||||
}
|
||||
}
|
||||
return hec;
|
||||
return chain;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,16 +16,21 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -34,162 +39,164 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Rick Evans
|
||||
* @since 14.09.2005
|
||||
*/
|
||||
public class UrlFilenameViewControllerTests {
|
||||
class UrlFilenameViewControllerTests {
|
||||
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
@SuppressWarnings("unused")
|
||||
private static Stream<Function<String, MockHttpServletRequest>> pathPatternsArguments() {
|
||||
return PathPatternsTestUtils.requestArguments();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void withPlainFilename() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
@PathPatternsParameterizedTest
|
||||
void withPlainFilename(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = requestFactory.apply("/index");
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("index");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withFilenamePlusExtension() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
@PathPatternsParameterizedTest
|
||||
void withFilenamePlusExtension(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = requestFactory.apply("/index.html");
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("index");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withFilenameAndMatrixVariables() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index;a=A;b=B");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
@PathPatternsParameterizedTest
|
||||
void withFilenameAndMatrixVariables(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = requestFactory.apply("/index;a=A;b=B");
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("index");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withPrefixAndSuffix() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
ctrl.setPrefix("mypre_");
|
||||
ctrl.setSuffix("_mysuf");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
@PathPatternsParameterizedTest
|
||||
void withPrefixAndSuffix(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
controller.setPrefix("mypre_");
|
||||
controller.setSuffix("_mysuf");
|
||||
MockHttpServletRequest request = requestFactory.apply("/index.html");
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("mypre_index_mysuf");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withPrefix() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
ctrl.setPrefix("mypre_");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
@PathPatternsParameterizedTest
|
||||
void withPrefix(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
controller.setPrefix("mypre_");
|
||||
MockHttpServletRequest request = requestFactory.apply("/index.html");
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("mypre_index");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withSuffix() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
ctrl.setSuffix("_mysuf");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
@PathPatternsParameterizedTest
|
||||
void withSuffix(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
controller.setSuffix("_mysuf");
|
||||
MockHttpServletRequest request = requestFactory.apply("/index.html");
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("index_mysuf");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiLevel() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/docs/cvs/commit.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
@PathPatternsParameterizedTest
|
||||
void multiLevel(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = requestFactory.apply("/docs/cvs/commit.html");
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("docs/cvs/commit");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiLevelWithMapping() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/docs/cvs/commit.html");
|
||||
@PathPatternsParameterizedTest
|
||||
void multiLevelWithMapping(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = requestFactory.apply("/docs/cvs/commit.html");
|
||||
exposePathInMapping(request, "/docs/**");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("cvs/commit");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiLevelMappingWithFallback() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/docs/cvs/commit.html");
|
||||
@PathPatternsParameterizedTest
|
||||
void multiLevelMappingWithFallback(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = requestFactory.apply("/docs/cvs/commit.html");
|
||||
exposePathInMapping(request, "/docs/cvs/commit.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("docs/cvs/commit");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withContextMapping() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
@PathPatternsParameterizedTest
|
||||
void withContextMapping(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myapp/docs/cvs/commit.html");
|
||||
request.setContextPath("/myapp");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("docs/cvs/commit");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingPrefixToNullCausesEmptyStringToBeUsed() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
ctrl.setPrefix(null);
|
||||
assertThat(ctrl.getPrefix()).as("For setPrefix(..) with null, the empty string must be used instead.").isNotNull();
|
||||
assertThat(ctrl.getPrefix()).as("For setPrefix(..) with null, the empty string must be used instead.").isEqualTo("");
|
||||
void settingPrefixToNullCausesEmptyStringToBeUsed() {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
controller.setPrefix(null);
|
||||
assertThat(controller.getPrefix())
|
||||
.as("For setPrefix(..) with null, the empty string must be used instead.")
|
||||
.isNotNull();
|
||||
assertThat(controller.getPrefix())
|
||||
.as("For setPrefix(..) with null, the empty string must be used instead.")
|
||||
.isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingSuffixToNullCausesEmptyStringToBeUsed() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
ctrl.setSuffix(null);
|
||||
assertThat(ctrl.getSuffix()).as("For setPrefix(..) with null, the empty string must be used instead.").isNotNull();
|
||||
assertThat(ctrl.getSuffix()).as("For setPrefix(..) with null, the empty string must be used instead.").isEqualTo("");
|
||||
void settingSuffixToNullCausesEmptyStringToBeUsed() {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
controller.setSuffix(null);
|
||||
assertThat(controller.getSuffix())
|
||||
.as("For setPrefix(..) with null, the empty string must be used instead.")
|
||||
.isNotNull();
|
||||
assertThat(controller.getSuffix())
|
||||
.as("For setPrefix(..) with null, the empty string must be used instead.")
|
||||
.isEqualTo("");
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the expected behavior, and it now has a test to prove it.
|
||||
* https://opensource.atlassian.com/projects/spring/browse/SPR-2789
|
||||
*/
|
||||
@Test
|
||||
public void nestedPathisUsedAsViewName_InBreakingChangeFromSpring12Line() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/products/view.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
@PathPatternsParameterizedTest
|
||||
void nestedPathisUsedAsViewName_InBreakingChangeFromSpring12Line(
|
||||
Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = requestFactory.apply("/products/view.html");
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("products/view");
|
||||
assertThat(mv.getModel().isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withFlashAttributes() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index");
|
||||
@PathPatternsParameterizedTest
|
||||
void withFlashAttributes(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
UrlFilenameViewController controller = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = requestFactory.apply("/index");
|
||||
request.setAttribute(DispatcherServlet.INPUT_FLASH_MAP_ATTRIBUTE, new ModelMap("name", "value"));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
ModelAndView mv = controller.handleRequest(request, new MockHttpServletResponse());
|
||||
assertThat(mv.getViewName()).isEqualTo("index");
|
||||
assertThat(mv.getModel().size()).isEqualTo(1);
|
||||
assertThat(mv.getModel().get("name")).isEqualTo("value");
|
||||
}
|
||||
|
||||
private void exposePathInMapping(MockHttpServletRequest request, String mapping) {
|
||||
String pathInMapping = this.pathMatcher.extractPathWithinPattern(mapping, request.getRequestURI());
|
||||
String pathInMapping = new AntPathMatcher().extractPathWithinPattern(mapping, request.getRequestURI());
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathInMapping);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -17,80 +17,83 @@
|
||||
package org.springframework.web.servlet.mvc;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link WebContentInterceptor}.
|
||||
* @author Rick Evans
|
||||
* @author Brian Clozel
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class WebContentInterceptorTests {
|
||||
class WebContentInterceptorTests {
|
||||
|
||||
private MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
private final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
private MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
private final WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
|
||||
private final Object handler = new Object();
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheResourcesConfiguration() throws Exception {
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
@SuppressWarnings("unused")
|
||||
private static Stream<Function<String, MockHttpServletRequest>> pathPatternsArguments() {
|
||||
return PathPatternsTestUtils.requestArguments();
|
||||
}
|
||||
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void cacheResourcesConfiguration(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
interceptor.setCacheSeconds(10);
|
||||
|
||||
interceptor.preHandle(request, response, null);
|
||||
interceptor.preHandle(requestFactory.apply("/"), response, handler);
|
||||
|
||||
Iterable<String> cacheControlHeaders = response.getHeaders("Cache-Control");
|
||||
assertThat(cacheControlHeaders).contains("max-age=10");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappedCacheConfigurationOverridesGlobal() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void mappedCacheConfigurationOverridesGlobal(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
Properties mappings = new Properties();
|
||||
mappings.setProperty("*/*handle.vm", "-1"); // was **/*handle.vm
|
||||
mappings.setProperty("/*/*handle.vm", "-1");
|
||||
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
interceptor.setCacheSeconds(10);
|
||||
interceptor.setCacheMappings(mappings);
|
||||
|
||||
// request.setRequestURI("http://localhost:7070/example/adminhandle.vm");
|
||||
request.setRequestURI("example/adminhandle.vm");
|
||||
interceptor.preHandle(request, response, null);
|
||||
MockHttpServletRequest request = requestFactory.apply("/example/adminhandle.vm");
|
||||
interceptor.preHandle(request, response, handler);
|
||||
|
||||
Iterable<String> cacheControlHeaders = response.getHeaders("Cache-Control");
|
||||
assertThat(cacheControlHeaders).isEmpty();
|
||||
|
||||
// request.setRequestURI("http://localhost:7070/example/bingo.html");
|
||||
request.setRequestURI("example/bingo.html");
|
||||
interceptor.preHandle(request, response, null);
|
||||
request = requestFactory.apply("/example/bingo.html");
|
||||
interceptor.preHandle(request, response, handler);
|
||||
|
||||
cacheControlHeaders = response.getHeaders("Cache-Control");
|
||||
assertThat(cacheControlHeaders).contains("max-age=10");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preventCacheConfiguration() throws Exception {
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
@PathPatternsParameterizedTest
|
||||
void preventCacheConfiguration(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
interceptor.setCacheSeconds(0);
|
||||
|
||||
interceptor.preHandle(request, response, null);
|
||||
interceptor.preHandle(requestFactory.apply("/"), response, handler);
|
||||
|
||||
Iterable<String> cacheControlHeaders = response.getHeaders("Cache-Control");
|
||||
assertThat(cacheControlHeaders).contains("no-store");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyCacheConfiguration() throws Exception {
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
@PathPatternsParameterizedTest
|
||||
void emptyCacheConfiguration(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
interceptor.setCacheSeconds(-1);
|
||||
|
||||
interceptor.preHandle(request, response, null);
|
||||
interceptor.preHandle(requestFactory.apply("/"), response, handler);
|
||||
|
||||
Iterable<String> expiresHeaders = response.getHeaders("Expires");
|
||||
assertThat(expiresHeaders).isEmpty();
|
||||
@@ -98,50 +101,45 @@ public class WebContentInterceptorTests {
|
||||
assertThat(cacheControlHeaders).isEmpty();
|
||||
}
|
||||
|
||||
// SPR-13252, SPR-14053
|
||||
@Test
|
||||
public void cachingConfigAndPragmaHeader() throws Exception {
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
interceptor.setCacheSeconds(10);
|
||||
@PathPatternsParameterizedTest // SPR-13252, SPR-14053
|
||||
void cachingConfigAndPragmaHeader(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
|
||||
interceptor.preHandle(request, response, null);
|
||||
interceptor.setCacheSeconds(10);
|
||||
interceptor.preHandle(requestFactory.apply("/"), response, handler);
|
||||
|
||||
assertThat(response.getHeader("Pragma")).isEqualTo("");
|
||||
assertThat(response.getHeader("Expires")).isEqualTo("");
|
||||
}
|
||||
|
||||
// SPR-13252, SPR-14053
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void http10CachingConfigAndPragmaHeader() throws Exception {
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
@PathPatternsParameterizedTest // SPR-13252, SPR-14053
|
||||
void http10CachingConfigAndPragmaHeader(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
|
||||
interceptor.setCacheSeconds(10);
|
||||
interceptor.setAlwaysMustRevalidate(true);
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
|
||||
interceptor.preHandle(request, response, null);
|
||||
interceptor.preHandle(requestFactory.apply("/"), response, handler);
|
||||
|
||||
assertThat(response.getHeader("Pragma")).isEqualTo("");
|
||||
assertThat(response.getHeader("Expires")).isEqualTo("");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void http10CachingConfigAndSpecificMapping() throws Exception {
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
@PathPatternsParameterizedTest
|
||||
void http10CachingConfigAndSpecificMapping(Function<String, MockHttpServletRequest> requestFactory) throws Exception {
|
||||
interceptor.setCacheSeconds(0);
|
||||
interceptor.setUseExpiresHeader(true);
|
||||
interceptor.setAlwaysMustRevalidate(true);
|
||||
Properties mappings = new Properties();
|
||||
mappings.setProperty("*/*.cache.html", "10"); // was **/*.cache.html
|
||||
mappings.setProperty("/*/*.cache.html", "10");
|
||||
interceptor.setCacheMappings(mappings);
|
||||
|
||||
// request.setRequestURI("https://example.org/foo/page.html");
|
||||
request.setRequestURI("foo/page.html");
|
||||
interceptor.preHandle(request, response, null);
|
||||
MockHttpServletRequest request = requestFactory.apply("/foo/page.html");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
interceptor.preHandle(request, response, handler);
|
||||
|
||||
Iterable<String> expiresHeaders = response.getHeaders("Expires");
|
||||
assertThat(expiresHeaders).hasSize(1);
|
||||
@@ -150,10 +148,9 @@ public class WebContentInterceptorTests {
|
||||
Iterable<String> pragmaHeaders = response.getHeaders("Pragma");
|
||||
assertThat(pragmaHeaders).containsExactly("no-cache");
|
||||
|
||||
// request.setRequestURI("https://example.org/page.cache.html");
|
||||
request = new MockHttpServletRequest("GET", "foo/page.cache.html");
|
||||
request = requestFactory.apply("/foo/page.cache.html");
|
||||
response = new MockHttpServletResponse();
|
||||
interceptor.preHandle(request, response, null);
|
||||
interceptor.preHandle(request, response, handler);
|
||||
|
||||
expiresHeaders = response.getHeaders("Expires");
|
||||
assertThat(expiresHeaders).hasSize(1);
|
||||
@@ -162,10 +159,9 @@ public class WebContentInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwsExceptionWithNullPathMatcher() throws Exception {
|
||||
WebContentInterceptor interceptor = new WebContentInterceptor();
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
interceptor.setPathMatcher(null));
|
||||
void throwsExceptionWithNullPathMatcher() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new WebContentInterceptor().setPathMatcher(null));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.condition;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PathPatternsRequestCondition}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class PathPatternsRequestConditionTests {
|
||||
|
||||
private static final PathPatternParser parser = new PathPatternParser();
|
||||
|
||||
|
||||
@Test
|
||||
void prependSlash() {
|
||||
assertThat(createCondition("foo").getPatternValues().iterator().next())
|
||||
.isEqualTo("/foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void prependNonEmptyPatternsOnly() {
|
||||
assertThat(createCondition("").getPatternValues().iterator().next())
|
||||
.as("Do not prepend empty patterns (SPR-8255)")
|
||||
.isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
void combineEmptySets() {
|
||||
PathPatternsRequestCondition c1 = createCondition();
|
||||
PathPatternsRequestCondition c2 = createCondition();
|
||||
PathPatternsRequestCondition c3 = c1.combine(c2);
|
||||
|
||||
assertThat(c3).isSameAs(c1);
|
||||
assertThat(c1.getPatternValues()).isSameAs(c2.getPatternValues()).containsExactly("");
|
||||
}
|
||||
|
||||
@Test
|
||||
void combineOnePatternWithEmptySet() {
|
||||
PathPatternsRequestCondition c1 = createCondition("/type1", "/type2");
|
||||
PathPatternsRequestCondition c2 = createCondition();
|
||||
|
||||
assertThat(c1.combine(c2)).isEqualTo(createCondition("/type1", "/type2"));
|
||||
|
||||
c1 = createCondition();
|
||||
c2 = createCondition("/method1", "/method2");
|
||||
|
||||
assertThat(c1.combine(c2)).isEqualTo(createCondition("/method1", "/method2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void combineMultiplePatterns() {
|
||||
PathPatternsRequestCondition c1 = createCondition("/t1", "/t2");
|
||||
PathPatternsRequestCondition c2 = createCondition("/m1", "/m2");
|
||||
|
||||
assertThat(c1.combine(c2)).isEqualTo(createCondition("/t1/m1", "/t1/m2", "/t2/m1", "/t2/m2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchDirectPath() {
|
||||
MockHttpServletRequest request = createRequest("/foo");
|
||||
|
||||
PathPatternsRequestCondition condition = createCondition("/foo");
|
||||
PathPatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchPattern() {
|
||||
MockHttpServletRequest request = createRequest("/foo/bar");
|
||||
|
||||
|
||||
PathPatternsRequestCondition condition = createCondition("/foo/*");
|
||||
PathPatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchPatternWithContextPath() {
|
||||
MockHttpServletRequest request = createRequest("/app", "/app/foo/bar");
|
||||
|
||||
PathPatternsRequestCondition condition = createCondition("/foo/*");
|
||||
PathPatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchSortPatterns() {
|
||||
MockHttpServletRequest request = createRequest("/foo/bar");
|
||||
|
||||
PathPatternsRequestCondition condition = createCondition("/**", "/foo/bar", "/foo/*");
|
||||
PathPatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
PathPatternsRequestCondition expected = createCondition("/foo/bar", "/foo/*", "/**");
|
||||
|
||||
assertThat(match).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchTrailingSlash() {
|
||||
MockHttpServletRequest request = createRequest("/foo/");
|
||||
|
||||
PathPatternsRequestCondition condition = createCondition("/foo");
|
||||
PathPatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatternValues().iterator().next()).as("Should match by default").isEqualTo("/foo");
|
||||
|
||||
PathPatternParser strictParser = new PathPatternParser();
|
||||
strictParser.setMatchOptionalTrailingSeparator(false);
|
||||
|
||||
condition = new PathPatternsRequestCondition(strictParser, "/foo");
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchPatternContainsExtension() {
|
||||
MockHttpServletRequest request = createRequest("/foo.html");
|
||||
PathPatternsRequestCondition match = createCondition("/foo.jpg").getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test // gh-22543
|
||||
void matchWithEmptyPatterns() {
|
||||
PathPatternsRequestCondition condition = createCondition();
|
||||
assertThat(condition.getMatchingCondition(createRequest(""))).isNotNull();
|
||||
assertThat(condition.getMatchingCondition(createRequest("/anything"))).isNull();
|
||||
|
||||
condition = condition.combine(createCondition());
|
||||
assertThat(condition.getMatchingCondition(createRequest(""))).isNotNull();
|
||||
assertThat(condition.getMatchingCondition(createRequest("/anything"))).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareEqualPatterns() {
|
||||
PathPatternsRequestCondition c1 = createCondition("/foo*");
|
||||
PathPatternsRequestCondition c2 = createCondition("/foo*");
|
||||
|
||||
assertThat(c1.compareTo(c2, createRequest("/foo"))).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void comparePatternSpecificity() {
|
||||
PathPatternsRequestCondition c1 = createCondition("/fo*");
|
||||
PathPatternsRequestCondition c2 = createCondition("/foo");
|
||||
|
||||
assertThat(c1.compareTo(c2, createRequest("/foo"))).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareNumberOfMatchingPatterns() {
|
||||
HttpServletRequest request = createRequest("/foo");
|
||||
|
||||
PathPatternsRequestCondition c1 = createCondition("/foo", "/bar");
|
||||
PathPatternsRequestCondition c2 = createCondition("/foo", "/f*");
|
||||
|
||||
PathPatternsRequestCondition match1 = c1.getMatchingCondition(request);
|
||||
PathPatternsRequestCondition match2 = c2.getMatchingCondition(request);
|
||||
|
||||
assertThat(match1.compareTo(match2, request)).isEqualTo(1);
|
||||
}
|
||||
|
||||
|
||||
private MockHttpServletRequest createRequest(String requestURI) {
|
||||
return createRequest("", requestURI);
|
||||
}
|
||||
|
||||
private MockHttpServletRequest createRequest(String contextPath, String requestURI) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestURI);
|
||||
request.setContextPath(contextPath);
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
return request;
|
||||
}
|
||||
|
||||
private PathPatternsRequestCondition createCondition(String... patterns) {
|
||||
return new PathPatternsRequestCondition(parser, patterns);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc.condition;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -24,28 +23,32 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PatternsRequestCondition}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class PatternsRequestConditionTests {
|
||||
class PatternsRequestConditionTests {
|
||||
|
||||
@Test
|
||||
public void prependSlash() {
|
||||
PatternsRequestCondition c = new PatternsRequestCondition("foo");
|
||||
assertThat(c.getPatterns().iterator().next()).isEqualTo("/foo");
|
||||
void prependSlash() {
|
||||
assertThat(new PatternsRequestCondition("foo").getPatterns().iterator().next())
|
||||
.isEqualTo("/foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prependNonEmptyPatternsOnly() {
|
||||
PatternsRequestCondition c = new PatternsRequestCondition("");
|
||||
assertThat(c.getPatterns().iterator().next()).as("Do not prepend empty patterns (SPR-8255)").isEqualTo("");
|
||||
void prependNonEmptyPatternsOnly() {
|
||||
assertThat(new PatternsRequestCondition("").getPatterns().iterator().next())
|
||||
.as("Do not prepend empty patterns (SPR-8255)")
|
||||
.isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineEmptySets() {
|
||||
void combineEmptySets() {
|
||||
PatternsRequestCondition c1 = new PatternsRequestCondition();
|
||||
PatternsRequestCondition c2 = new PatternsRequestCondition();
|
||||
PatternsRequestCondition c3 = c1.combine(c2);
|
||||
@@ -55,7 +58,7 @@ public class PatternsRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineOnePatternWithEmptySet() {
|
||||
void combineOnePatternWithEmptySet() {
|
||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/type1", "/type2");
|
||||
PatternsRequestCondition c2 = new PatternsRequestCondition();
|
||||
|
||||
@@ -68,7 +71,7 @@ public class PatternsRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineMultiplePatterns() {
|
||||
void combineMultiplePatterns() {
|
||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/t1", "/t2");
|
||||
PatternsRequestCondition c2 = new PatternsRequestCondition("/m1", "/m2");
|
||||
|
||||
@@ -76,42 +79,49 @@ public class PatternsRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchDirectPath() {
|
||||
void matchDirectPath() {
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo"));
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(initRequest("/foo"));
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchPattern() {
|
||||
void matchPattern() {
|
||||
MockHttpServletRequest request = initRequest("/foo/bar");
|
||||
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition("/foo/*");
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo/bar"));
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchSortPatterns() {
|
||||
void matchSortPatterns() {
|
||||
MockHttpServletRequest request = initRequest("/foo/bar");
|
||||
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition("/**", "/foo/bar", "/foo/*");
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo/bar"));
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
PatternsRequestCondition expected = new PatternsRequestCondition("/foo/bar", "/foo/*", "/**");
|
||||
|
||||
assertThat(match).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchSuffixPattern() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.html");
|
||||
void matchSuffixPattern() {
|
||||
MockHttpServletRequest request = initRequest("/foo.html");
|
||||
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition("/{foo}");
|
||||
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().iterator().next()).isEqualTo("/{foo}.*");
|
||||
|
||||
boolean useSuffixPatternMatch = false;
|
||||
condition = new PatternsRequestCondition(new String[] {"/{foo}"}, null, null, useSuffixPatternMatch, false);
|
||||
useSuffixPatternMatch = false;
|
||||
condition = new PatternsRequestCondition(
|
||||
new String[] {"/{foo}"}, null, null, useSuffixPatternMatch, false);
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
@@ -119,17 +129,17 @@ public class PatternsRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test // SPR-8410
|
||||
public void matchSuffixPatternUsingFileExtensions() {
|
||||
void matchSuffixPatternUsingFileExtensions() {
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition(
|
||||
new String[] {"/jobs/{jobName}"}, null, null, true, false, Collections.singletonList("json"));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/jobs/my.job");
|
||||
MockHttpServletRequest request = initRequest("/jobs/my.job");
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatterns().iterator().next()).isEqualTo("/jobs/{jobName}");
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/jobs/my.job.json");
|
||||
request = initRequest("/jobs/my.job.json");
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
@@ -137,24 +147,24 @@ public class PatternsRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchSuffixPatternUsingFileExtensions2() {
|
||||
void matchSuffixPatternUsingFileExtensions2() {
|
||||
PatternsRequestCondition condition1 = new PatternsRequestCondition(
|
||||
new String[] {"/prefix"}, null, null, true, false, Arrays.asList("json"));
|
||||
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 = new MockHttpServletRequest("GET", "/prefix/suffix.json");
|
||||
MockHttpServletRequest request = initRequest("/prefix/suffix.json");
|
||||
PatternsRequestCondition match = combined.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchTrailingSlash() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/");
|
||||
void matchTrailingSlash() {
|
||||
MockHttpServletRequest request = initRequest("/foo/");
|
||||
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(request);
|
||||
@@ -162,7 +172,7 @@ public class PatternsRequestConditionTests {
|
||||
assertThat(match).isNotNull();
|
||||
assertThat(match.getPatterns().iterator().next()).as("Should match by default").isEqualTo("/foo/");
|
||||
|
||||
condition = new PatternsRequestCondition(new String[] {"/foo"}, null, null, false, true);
|
||||
condition = new PatternsRequestCondition(new String[] {"/foo"}, true, null);
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
@@ -170,53 +180,53 @@ public class PatternsRequestConditionTests {
|
||||
.as("Trailing slash should be insensitive to useSuffixPatternMatch settings (SPR-6164, SPR-5636)")
|
||||
.isEqualTo("/foo/");
|
||||
|
||||
condition = new PatternsRequestCondition(new String[] {"/foo"}, null, null, false);
|
||||
condition = new PatternsRequestCondition(new String[] {"/foo"}, false, null);
|
||||
match = condition.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchPatternContainsExtension() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.html");
|
||||
void matchPatternContainsExtension() {
|
||||
MockHttpServletRequest request = initRequest("/foo.html");
|
||||
PatternsRequestCondition match = new PatternsRequestCondition("/foo.jpg").getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test // gh-22543
|
||||
public void matchWithEmptyPatterns() {
|
||||
void matchWithEmptyPatterns() {
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition();
|
||||
assertThat(condition.getMatchingCondition(new MockHttpServletRequest("GET", ""))).isNotNull();
|
||||
assertThat(condition.getMatchingCondition(new MockHttpServletRequest("GET", "/anything"))).isNull();
|
||||
assertThat(condition.getMatchingCondition(initRequest(""))).isNotNull();
|
||||
assertThat(condition.getMatchingCondition(initRequest("/anything"))).isNull();
|
||||
|
||||
condition = condition.combine(new PatternsRequestCondition());
|
||||
assertThat(condition.getMatchingCondition(new MockHttpServletRequest("GET", ""))).isNotNull();
|
||||
assertThat(condition.getMatchingCondition(new MockHttpServletRequest("GET", "/anything"))).isNull();
|
||||
assertThat(condition.getMatchingCondition(initRequest(""))).isNotNull();
|
||||
assertThat(condition.getMatchingCondition(initRequest("/anything"))).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareEqualPatterns() {
|
||||
void compareEqualPatterns() {
|
||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo*");
|
||||
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo*");
|
||||
|
||||
assertThat(c1.compareTo(c2, new MockHttpServletRequest("GET", "/foo"))).isEqualTo(0);
|
||||
assertThat(c1.compareTo(c2, initRequest("/foo"))).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void comparePatternSpecificity() {
|
||||
void comparePatternSpecificity() {
|
||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/fo*");
|
||||
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo");
|
||||
|
||||
assertThat(c1.compareTo(c2, new MockHttpServletRequest("GET", "/foo"))).isEqualTo(1);
|
||||
assertThat(c1.compareTo(c2, initRequest("/foo"))).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareNumberOfMatchingPatterns() {
|
||||
HttpServletRequest request = new MockHttpServletRequest("GET", "/foo.html");
|
||||
void compareNumberOfMatchingPatterns() {
|
||||
HttpServletRequest request = initRequest("/foo.html");
|
||||
|
||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo", "*.jpeg");
|
||||
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo", "*.html");
|
||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo.html", "*.jpeg");
|
||||
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo.html", "*.html");
|
||||
|
||||
PatternsRequestCondition match1 = c1.getMatchingCondition(request);
|
||||
PatternsRequestCondition match2 = c2.getMatchingCondition(request);
|
||||
@@ -224,4 +234,11 @@ public class PatternsRequestConditionTests {
|
||||
assertThat(match1.compareTo(match2, request)).isEqualTo(1);
|
||||
}
|
||||
|
||||
|
||||
private MockHttpServletRequest initRequest(String requestUri) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -31,6 +32,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.RequestPath;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
@@ -49,14 +51,11 @@ import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.handler.MappedInterceptor;
|
||||
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
|
||||
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@@ -67,9 +66,25 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class RequestMappingInfoHandlerMappingTests {
|
||||
class RequestMappingInfoHandlerMappingTests {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<?> pathPatternsArguments() {
|
||||
TestController controller = new TestController();
|
||||
|
||||
TestRequestMappingInfoHandlerMapping mapping1 = new TestRequestMappingInfoHandlerMapping();
|
||||
mapping1.setPatternParser(new PathPatternParser());
|
||||
|
||||
TestRequestMappingInfoHandlerMapping mapping2 = new TestRequestMappingInfoHandlerMapping();
|
||||
mapping2.setRemoveSemicolonContent(false);
|
||||
|
||||
return Stream.of(mapping1, mapping2).peek(mapping -> {
|
||||
mapping.setApplicationContext(new StaticWebApplicationContext());
|
||||
mapping.registerHandler(controller);
|
||||
mapping.afterPropertiesSet();
|
||||
});
|
||||
}
|
||||
|
||||
private TestRequestMappingInfoHandlerMapping handlerMapping;
|
||||
|
||||
private HandlerMethod fooMethod;
|
||||
|
||||
@@ -81,148 +96,145 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
TestController testController = new TestController();
|
||||
|
||||
this.fooMethod = new HandlerMethod(testController, "foo");
|
||||
this.fooParamMethod = new HandlerMethod(testController, "fooParam");
|
||||
this.barMethod = new HandlerMethod(testController, "bar");
|
||||
this.emptyMethod = new HandlerMethod(testController, "empty");
|
||||
|
||||
this.handlerMapping = new TestRequestMappingInfoHandlerMapping();
|
||||
this.handlerMapping.registerHandler(testController);
|
||||
this.handlerMapping.setRemoveSemicolonContent(false);
|
||||
void setup() throws Exception {
|
||||
TestController controller = new TestController();
|
||||
this.fooMethod = new HandlerMethod(controller, "foo");
|
||||
this.fooParamMethod = new HandlerMethod(controller, "fooParam");
|
||||
this.barMethod = new HandlerMethod(controller, "bar");
|
||||
this.emptyMethod = new HandlerMethod(controller, "empty");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getMappingPathPatterns() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void getMappingPathPatterns(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
String[] patterns = {"/foo/*", "/foo", "/bar/*", "/bar"};
|
||||
RequestMappingInfo info = RequestMappingInfo.paths(patterns).build();
|
||||
Set<String> actual = this.handlerMapping.getMappingPathPatterns(info);
|
||||
RequestMappingInfo info = mapping.createInfo(patterns);
|
||||
Set<String> actual = mapping.getMappingPathPatterns(info);
|
||||
|
||||
assertThat(actual).isEqualTo(new HashSet<>(Arrays.asList(patterns)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerDirectMatch() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void getHandlerDirectMatch(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
HandlerMethod handlerMethod = getHandler(request);
|
||||
HandlerMethod handlerMethod = getHandler(mapping, request);
|
||||
|
||||
assertThat(handlerMethod.getMethod()).isEqualTo(this.fooMethod.getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerGlobMatch() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void getHandlerGlobMatch(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bar");
|
||||
HandlerMethod handlerMethod = getHandler(request);
|
||||
HandlerMethod handlerMethod = getHandler(mapping, request);
|
||||
assertThat(handlerMethod.getMethod()).isEqualTo(this.barMethod.getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerEmptyPathMatch() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void getHandlerEmptyPathMatch(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
HandlerMethod handlerMethod = getHandler(request);
|
||||
HandlerMethod handlerMethod = getHandler(mapping, request);
|
||||
|
||||
assertThat(handlerMethod.getMethod()).isEqualTo(this.emptyMethod.getMethod());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/");
|
||||
handlerMethod = getHandler(request);
|
||||
handlerMethod = getHandler(mapping, request);
|
||||
|
||||
assertThat(handlerMethod.getMethod()).isEqualTo(this.emptyMethod.getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerBestMatch() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void getHandlerBestMatch(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
request.setParameter("p", "anything");
|
||||
HandlerMethod handlerMethod = getHandler(request);
|
||||
HandlerMethod handlerMethod = getHandler(mapping, request);
|
||||
|
||||
assertThat(handlerMethod.getMethod()).isEqualTo(this.fooParamMethod.getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerRequestMethodNotAllowed() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void getHandlerRequestMethodNotAllowed(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/bar");
|
||||
assertThatExceptionOfType(HttpRequestMethodNotSupportedException.class).isThrownBy(() ->
|
||||
this.handlerMapping.getHandler(request))
|
||||
.satisfies(ex -> assertThat(ex.getSupportedMethods()).containsExactly("GET", "HEAD"));
|
||||
assertThatExceptionOfType(HttpRequestMethodNotSupportedException.class)
|
||||
.isThrownBy(() -> mapping.getHandler(request))
|
||||
.satisfies(ex -> assertThat(ex.getSupportedMethods()).containsExactly("GET", "HEAD"));
|
||||
}
|
||||
|
||||
@Test // SPR-9603
|
||||
public void getHandlerRequestMethodMatchFalsePositive() throws Exception {
|
||||
@PathPatternsParameterizedTest // SPR-9603
|
||||
void getHandlerRequestMethodMatchFalsePositive(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/users");
|
||||
request.addHeader("Accept", "application/xml");
|
||||
this.handlerMapping.registerHandler(new UserController());
|
||||
assertThatExceptionOfType(HttpMediaTypeNotAcceptableException.class).isThrownBy(() ->
|
||||
this.handlerMapping.getHandler(request));
|
||||
mapping.registerHandler(new UserController());
|
||||
assertThatExceptionOfType(HttpMediaTypeNotAcceptableException.class)
|
||||
.isThrownBy(() -> mapping.getHandler(request));
|
||||
}
|
||||
|
||||
@Test // SPR-8462
|
||||
public void getHandlerMediaTypeNotSupported() throws Exception {
|
||||
testHttpMediaTypeNotSupportedException("/person/1");
|
||||
testHttpMediaTypeNotSupportedException("/person/1/");
|
||||
testHttpMediaTypeNotSupportedException("/person/1.json");
|
||||
@PathPatternsParameterizedTest // SPR-8462
|
||||
void getHandlerMediaTypeNotSupported(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
testHttpMediaTypeNotSupportedException(mapping, "/person/1");
|
||||
testHttpMediaTypeNotSupportedException(mapping, "/person/1/");
|
||||
testHttpMediaTypeNotSupportedException(mapping, "/person/1.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerHttpOptions() throws Exception {
|
||||
testHttpOptions("/foo", "GET,HEAD,OPTIONS");
|
||||
testHttpOptions("/person/1", "PUT,OPTIONS");
|
||||
testHttpOptions("/persons", "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS");
|
||||
testHttpOptions("/something", "PUT,POST");
|
||||
@PathPatternsParameterizedTest
|
||||
void getHandlerHttpOptions(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
testHttpOptions(mapping, "/foo", "GET,HEAD,OPTIONS");
|
||||
testHttpOptions(mapping, "/person/1", "PUT,OPTIONS");
|
||||
testHttpOptions(mapping, "/persons", "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS");
|
||||
testHttpOptions(mapping, "/something", "PUT,POST");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerTestInvalidContentType() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void getHandlerTestInvalidContentType(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/person/1");
|
||||
request.setContentType("bogus");
|
||||
assertThatExceptionOfType(HttpMediaTypeNotSupportedException.class).isThrownBy(() ->
|
||||
this.handlerMapping.getHandler(request))
|
||||
.withMessage("Invalid mime type \"bogus\": does not contain '/'");
|
||||
assertThatExceptionOfType(HttpMediaTypeNotSupportedException.class)
|
||||
.isThrownBy(() -> mapping.getHandler(request))
|
||||
.withMessage("Invalid mime type \"bogus\": does not contain '/'");
|
||||
}
|
||||
|
||||
@Test // SPR-8462
|
||||
public void getHandlerMediaTypeNotAccepted() throws Exception {
|
||||
testHttpMediaTypeNotAcceptableException("/persons");
|
||||
testHttpMediaTypeNotAcceptableException("/persons/");
|
||||
testHttpMediaTypeNotAcceptableException("/persons.json");
|
||||
@PathPatternsParameterizedTest // SPR-8462
|
||||
void getHandlerMediaTypeNotAccepted(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
testHttpMediaTypeNotAcceptableException(mapping, "/persons");
|
||||
testHttpMediaTypeNotAcceptableException(mapping, "/persons/");
|
||||
if (mapping.getPatternParser() == null) {
|
||||
testHttpMediaTypeNotAcceptableException(mapping, "/persons.json");
|
||||
}
|
||||
}
|
||||
|
||||
@Test // SPR-12854
|
||||
public void getHandlerUnsatisfiedServletRequestParameterException() throws Exception {
|
||||
@PathPatternsParameterizedTest // SPR-12854
|
||||
void getHandlerUnsatisfiedServletRequestParameterException(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/params");
|
||||
assertThatExceptionOfType(UnsatisfiedServletRequestParameterException.class).isThrownBy(() ->
|
||||
this.handlerMapping.getHandler(request))
|
||||
.satisfies(ex -> assertThat(ex.getParamConditionGroups().stream().map(group -> group[0]))
|
||||
.containsExactlyInAnyOrder("foo=bar", "bar=baz"));
|
||||
assertThatExceptionOfType(UnsatisfiedServletRequestParameterException.class)
|
||||
.isThrownBy(() -> mapping.getHandler(request))
|
||||
.satisfies(ex -> assertThat(ex.getParamConditionGroups().stream().map(group -> group[0]))
|
||||
.containsExactlyInAnyOrder("foo=bar", "bar=baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerProducibleMediaTypesAttribute() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void getHandlerProducibleMediaTypesAttribute(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/content");
|
||||
request.addHeader("Accept", "application/xml");
|
||||
this.handlerMapping.getHandler(request);
|
||||
mapping.getHandler(request);
|
||||
|
||||
String name = HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE;
|
||||
assertThat(request.getAttribute(name)).isEqualTo(Collections.singleton(MediaType.APPLICATION_XML));
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/content");
|
||||
request.addHeader("Accept", "application/json");
|
||||
this.handlerMapping.getHandler(request);
|
||||
mapping.getHandler(request);
|
||||
|
||||
assertThat(request.getAttribute(name)).as("Negated expression shouldn't be listed as producible type").isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHandlerMappedInterceptors() throws Exception {
|
||||
void getHandlerMappedInterceptors() throws Exception {
|
||||
String path = "/foo";
|
||||
HandlerInterceptor interceptor = new HandlerInterceptor() {};
|
||||
MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[] {path}, interceptor);
|
||||
|
||||
TestRequestMappingInfoHandlerMapping mapping = new TestRequestMappingInfoHandlerMapping();
|
||||
mapping.registerHandler(new TestController());
|
||||
mapping.setInterceptors(new Object[] { mappedInterceptor });
|
||||
mapping.setInterceptors(mappedInterceptor);
|
||||
mapping.setApplicationContext(new StaticWebApplicationContext());
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(new MockHttpServletRequest("GET", path));
|
||||
@@ -235,12 +247,12 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void handleMatchUriTemplateVariables() {
|
||||
@PathPatternsParameterizedTest
|
||||
void handleMatchUriTemplateVariables(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
RequestMappingInfo key = RequestMappingInfo.paths("/{path1}/{path2}").build();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/1/2");
|
||||
String lookupPath = new UrlPathHelper().getLookupPathForRequest(request);
|
||||
this.handlerMapping.handleMatch(key, lookupPath, request);
|
||||
mapping.handleMatch(key, lookupPath, request);
|
||||
|
||||
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
Map<String, String> uriVariables = (Map<String, String>) request.getAttribute(name);
|
||||
@@ -251,8 +263,8 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test // SPR-9098
|
||||
public void handleMatchUriTemplateVariablesDecode() {
|
||||
@PathPatternsParameterizedTest // SPR-9098
|
||||
void handleMatchUriTemplateVariablesDecode(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
RequestMappingInfo key = RequestMappingInfo.paths("/{group}/{identifier}").build();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/group/a%2Fb");
|
||||
|
||||
@@ -260,8 +272,8 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
pathHelper.setUrlDecode(false);
|
||||
String lookupPath = pathHelper.getLookupPathForRequest(request);
|
||||
|
||||
this.handlerMapping.setUrlPathHelper(pathHelper);
|
||||
this.handlerMapping.handleMatch(key, lookupPath, request);
|
||||
mapping.setUrlPathHelper(pathHelper);
|
||||
mapping.handleMatch(key, lookupPath, request);
|
||||
|
||||
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
Map<String, String> uriVariables = (Map<String, String>) request.getAttribute(name);
|
||||
@@ -271,32 +283,32 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
assertThat(uriVariables.get("identifier")).isEqualTo("a/b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleMatchBestMatchingPatternAttribute() {
|
||||
@PathPatternsParameterizedTest
|
||||
void handleMatchBestMatchingPatternAttribute(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
RequestMappingInfo key = RequestMappingInfo.paths("/{path1}/2", "/**").build();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/1/2");
|
||||
this.handlerMapping.handleMatch(key, "/1/2", request);
|
||||
mapping.handleMatch(key, "/1/2", request);
|
||||
|
||||
assertThat(request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)).isEqualTo("/{path1}/2");
|
||||
}
|
||||
|
||||
@Test // gh-22543
|
||||
public void handleMatchBestMatchingPatternAttributeNoPatternsDefined() {
|
||||
@PathPatternsParameterizedTest // gh-22543
|
||||
void handleMatchBestMatchingPatternAttributeNoPatternsDefined(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
String path = "";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", path);
|
||||
this.handlerMapping.handleMatch(RequestMappingInfo.paths().build(), path, request);
|
||||
mapping.handleMatch(RequestMappingInfo.paths().build(), path, request);
|
||||
assertThat(request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)).isEqualTo(path);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleMatchMatrixVariables() {
|
||||
@PathPatternsParameterizedTest
|
||||
void handleMatchMatrixVariables(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
MockHttpServletRequest request;
|
||||
MultiValueMap<String, String> matrixVariables;
|
||||
Map<String, String> uriVariables;
|
||||
|
||||
// URI var parsed into path variable + matrix params..
|
||||
request = new MockHttpServletRequest();
|
||||
handleMatch(request, "/{cars}", "/cars;colors=red,blue,green;year=2012");
|
||||
request = new MockHttpServletRequest("GET", "/cars;colors=red,blue,green;year=2012");
|
||||
handleMatch(mapping, request, "/{cars}", request.getRequestURI());
|
||||
|
||||
matrixVariables = getMatrixVariables(request, "cars");
|
||||
uriVariables = getUriTemplateVariables(request);
|
||||
@@ -307,8 +319,8 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
assertThat(uriVariables.get("cars")).isEqualTo("cars");
|
||||
|
||||
// URI var with regex for path variable, and URI var for matrix params..
|
||||
request = new MockHttpServletRequest();
|
||||
handleMatch(request, "/{cars:[^;]+}{params}", "/cars;colors=red,blue,green;year=2012");
|
||||
request = new MockHttpServletRequest("GET", "/cars;colors=red,blue,green;year=2012");
|
||||
handleMatch(mapping, request, "/{cars:[^;]+}{params}", request.getRequestURI());
|
||||
|
||||
matrixVariables = getMatrixVariables(request, "params");
|
||||
uriVariables = getUriTemplateVariables(request);
|
||||
@@ -317,11 +329,13 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
assertThat(matrixVariables.get("colors")).isEqualTo(Arrays.asList("red", "blue", "green"));
|
||||
assertThat(matrixVariables.getFirst("year")).isEqualTo("2012");
|
||||
assertThat(uriVariables.get("cars")).isEqualTo("cars");
|
||||
assertThat(uriVariables.get("params")).isEqualTo(";colors=red,blue,green;year=2012");
|
||||
if (mapping.getPatternParser() == null) {
|
||||
assertThat(uriVariables.get("params")).isEqualTo(";colors=red,blue,green;year=2012");
|
||||
}
|
||||
|
||||
// URI var with regex for path variable, and (empty) URI var for matrix params..
|
||||
request = new MockHttpServletRequest();
|
||||
handleMatch(request, "/{cars:[^;]+}{params}", "/cars");
|
||||
request = new MockHttpServletRequest("GET", "/cars");
|
||||
handleMatch(mapping, request, "/{cars:[^;]+}{params}", request.getRequestURI());
|
||||
|
||||
matrixVariables = getMatrixVariables(request, "params");
|
||||
uriVariables = getUriTemplateVariables(request);
|
||||
@@ -331,32 +345,38 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
assertThat(uriVariables.get("params")).isEqualTo("");
|
||||
|
||||
// SPR-11897
|
||||
request = new MockHttpServletRequest();
|
||||
handleMatch(request, "/{foo}", "/a=42;b=c");
|
||||
request = new MockHttpServletRequest("GET", "/a=42;b=c");
|
||||
handleMatch(mapping, request, "/{foo}", request.getRequestURI());
|
||||
|
||||
matrixVariables = getMatrixVariables(request, "foo");
|
||||
uriVariables = getUriTemplateVariables(request);
|
||||
|
||||
assertThat(matrixVariables).isNotNull();
|
||||
assertThat(matrixVariables.size()).isEqualTo(2);
|
||||
assertThat(matrixVariables.getFirst("a")).isEqualTo("42");
|
||||
assertThat(matrixVariables.getFirst("b")).isEqualTo("c");
|
||||
assertThat(uriVariables.get("foo")).isEqualTo("a=42");
|
||||
if (mapping.getPatternParser() != null) {
|
||||
assertThat(matrixVariables.size()).isEqualTo(1);
|
||||
assertThat(matrixVariables.getFirst("b")).isEqualTo("c");
|
||||
assertThat(uriVariables.get("foo")).isEqualTo("a=42");
|
||||
}
|
||||
else {
|
||||
assertThat(matrixVariables.size()).isEqualTo(2);
|
||||
assertThat(matrixVariables.getFirst("a")).isEqualTo("42");
|
||||
assertThat(matrixVariables.getFirst("b")).isEqualTo("c");
|
||||
assertThat(uriVariables.get("foo")).isEqualTo("a=42");
|
||||
}
|
||||
}
|
||||
|
||||
@Test // SPR-10140, SPR-16867
|
||||
public void handleMatchMatrixVariablesDecoding() {
|
||||
@PathPatternsParameterizedTest // SPR-10140, SPR-16867
|
||||
void handleMatchMatrixVariablesDecoding(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
|
||||
MockHttpServletRequest request;
|
||||
if (mapping.getPatternParser() == null) {
|
||||
UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
urlPathHelper.setUrlDecode(false);
|
||||
urlPathHelper.setRemoveSemicolonContent(false);
|
||||
mapping.setUrlPathHelper(urlPathHelper);
|
||||
}
|
||||
|
||||
UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
urlPathHelper.setUrlDecode(false);
|
||||
urlPathHelper.setRemoveSemicolonContent(false);
|
||||
|
||||
this.handlerMapping.setUrlPathHelper(urlPathHelper);
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
handleMatch(request, "/{cars}", "/cars;mvar=a%2Fb");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/cars;mvar=a%2Fb");
|
||||
handleMatch(mapping, request, "/{cars}", request.getRequestURI());
|
||||
|
||||
MultiValueMap<String, String> matrixVariables = getMatrixVariables(request, "cars");
|
||||
Map<String, String> uriVariables = getUriTemplateVariables(request);
|
||||
@@ -366,24 +386,27 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
assertThat(uriVariables.get("cars")).isEqualTo("cars");
|
||||
}
|
||||
|
||||
private HandlerMethod getHandler(
|
||||
TestRequestMappingInfoHandlerMapping mapping, MockHttpServletRequest request) throws Exception {
|
||||
|
||||
private HandlerMethod getHandler(MockHttpServletRequest request) throws Exception {
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
assertThat(chain).isNotNull();
|
||||
return (HandlerMethod) chain.getHandler();
|
||||
}
|
||||
|
||||
private void testHttpMediaTypeNotSupportedException(String url) throws Exception {
|
||||
private void testHttpMediaTypeNotSupportedException(TestRequestMappingInfoHandlerMapping mapping, String url) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("PUT", url);
|
||||
request.setContentType("application/json");
|
||||
assertThatExceptionOfType(HttpMediaTypeNotSupportedException.class).isThrownBy(() ->
|
||||
this.handlerMapping.getHandler(request))
|
||||
.satisfies(ex -> assertThat(ex.getSupportedMediaTypes()).containsExactly(MediaType.APPLICATION_XML));
|
||||
assertThatExceptionOfType(HttpMediaTypeNotSupportedException.class)
|
||||
.isThrownBy(() -> mapping.getHandler(request))
|
||||
.satisfies(ex -> assertThat(ex.getSupportedMediaTypes()).containsExactly(MediaType.APPLICATION_XML));
|
||||
}
|
||||
|
||||
private void testHttpOptions(String requestURI, String allowHeader) throws Exception {
|
||||
private void testHttpOptions(
|
||||
TestRequestMappingInfoHandlerMapping mapping, String requestURI, String allowHeader) throws Exception {
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", requestURI);
|
||||
HandlerMethod handlerMethod = getHandler(request);
|
||||
HandlerMethod handlerMethod = getHandler(mapping, request);
|
||||
|
||||
ServletWebRequest webRequest = new ServletWebRequest(request);
|
||||
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
|
||||
@@ -394,17 +417,22 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
assertThat(((HttpHeaders) result).getFirst("Allow")).isEqualTo(allowHeader);
|
||||
}
|
||||
|
||||
private void testHttpMediaTypeNotAcceptableException(String url) throws Exception {
|
||||
private void testHttpMediaTypeNotAcceptableException(TestRequestMappingInfoHandlerMapping mapping, String url) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", url);
|
||||
request.addHeader("Accept", "application/json");
|
||||
assertThatExceptionOfType(HttpMediaTypeNotAcceptableException.class).isThrownBy(() ->
|
||||
this.handlerMapping.getHandler(request))
|
||||
mapping.getHandler(request))
|
||||
.satisfies(ex -> assertThat(ex.getSupportedMediaTypes()).containsExactly(MediaType.APPLICATION_XML));
|
||||
}
|
||||
|
||||
private void handleMatch(MockHttpServletRequest request, String pattern, String lookupPath) {
|
||||
RequestMappingInfo info = RequestMappingInfo.paths(pattern).build();
|
||||
this.handlerMapping.handleMatch(info, lookupPath, request);
|
||||
private void handleMatch(TestRequestMappingInfoHandlerMapping mapping,
|
||||
MockHttpServletRequest request, String pattern, String lookupPath) {
|
||||
|
||||
if (mapping.getPatternParser() != null) {
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
}
|
||||
|
||||
mapping.handleMatch(mapping.createInfo(pattern), lookupPath, request);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -494,7 +522,8 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
|
||||
private static class TestRequestMappingInfoHandlerMapping extends RequestMappingInfoHandlerMapping {
|
||||
|
||||
public void registerHandler(Object handler) {
|
||||
|
||||
void registerHandler(Object handler) {
|
||||
super.detectHandlerMethods(handler);
|
||||
}
|
||||
|
||||
@@ -507,18 +536,46 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
RequestMapping annot = AnnotationUtils.findAnnotation(method, RequestMapping.class);
|
||||
if (annot != null) {
|
||||
return new RequestMappingInfo(
|
||||
new PatternsRequestCondition(annot.value(), getUrlPathHelper(), getPathMatcher(), true, true),
|
||||
new RequestMethodsRequestCondition(annot.method()),
|
||||
new ParamsRequestCondition(annot.params()),
|
||||
new HeadersRequestCondition(annot.headers()),
|
||||
new ConsumesRequestCondition(annot.consumes(), annot.headers()),
|
||||
new ProducesRequestCondition(annot.produces(), annot.headers()), null);
|
||||
return RequestMappingInfo.paths(annot.value())
|
||||
.methods(annot.method())
|
||||
.params(annot.params())
|
||||
.headers(annot.headers())
|
||||
.consumes(annot.consumes())
|
||||
.produces(annot.produces())
|
||||
.options(getBuilderConfig())
|
||||
.build();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
RequestMappingInfo createInfo(String... patterns) {
|
||||
return RequestMappingInfo.paths(patterns).options(getBuilderConfig()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String initLookupPath(HttpServletRequest request) {
|
||||
// At runtime this is done by the DispatcherServlet
|
||||
if (getPatternParser() != null) {
|
||||
RequestPath requestPath = ServletRequestPathUtils.parseAndCache(request);
|
||||
return requestPath.pathWithinApplication().value();
|
||||
}
|
||||
return super.initLookupPath(request);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.web.servlet.mvc.method;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -26,13 +27,16 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.HEAD;
|
||||
import static org.springframework.web.servlet.mvc.method.RequestMappingInfo.paths;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link RequestMappingInfo} tests.
|
||||
@@ -40,15 +44,22 @@ import static org.springframework.web.servlet.mvc.method.RequestMappingInfo.path
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class RequestMappingInfoTests {
|
||||
class RequestMappingInfoTests {
|
||||
|
||||
@Test
|
||||
public void createEmpty() {
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<RequestMappingInfo.Builder> pathPatternsArguments() {
|
||||
RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();
|
||||
config.setPatternParser(new PathPatternParser());
|
||||
return Stream.of(RequestMappingInfo.paths().options(config), RequestMappingInfo.paths());
|
||||
}
|
||||
|
||||
RequestMappingInfo info = paths().build();
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void createEmpty(RequestMappingInfo.Builder infoBuilder) {
|
||||
|
||||
// gh-22543
|
||||
assertThat(info.getPatternsCondition().getPatterns()).isEqualTo(Collections.singleton(""));
|
||||
RequestMappingInfo info = infoBuilder.build();
|
||||
assertThat(info.getPatternValues()).isEqualTo(Collections.singleton(""));
|
||||
assertThat(info.getMethodsCondition().getMethods().size()).isEqualTo(0);
|
||||
assertThat(info.getParamsCondition()).isNotNull();
|
||||
assertThat(info.getHeadersCondition()).isNotNull();
|
||||
@@ -56,7 +67,8 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info.getProducesCondition().isEmpty()).isEqualTo(true);
|
||||
assertThat(info.getCustomCondition()).isNull();
|
||||
|
||||
RequestMappingInfo anotherInfo = paths().build();
|
||||
RequestMappingInfo anotherInfo = infoBuilder.build();
|
||||
assertThat(info.getActivePatternsCondition()).isSameAs(anotherInfo.getActivePatternsCondition());
|
||||
assertThat(info.getPatternsCondition()).isSameAs(anotherInfo.getPatternsCondition());
|
||||
assertThat(info.getMethodsCondition()).isSameAs(anotherInfo.getMethodsCondition());
|
||||
assertThat(info.getParamsCondition()).isSameAs(anotherInfo.getParamsCondition());
|
||||
@@ -66,7 +78,7 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info.getCustomCondition()).isSameAs(anotherInfo.getCustomCondition());
|
||||
|
||||
RequestMappingInfo result = info.combine(anotherInfo);
|
||||
assertThat(info.getPatternsCondition()).isSameAs(result.getPatternsCondition());
|
||||
assertThat(info.getActivePatternsCondition()).isSameAs(result.getActivePatternsCondition());
|
||||
assertThat(info.getMethodsCondition()).isSameAs(result.getMethodsCondition());
|
||||
assertThat(info.getParamsCondition()).isSameAs(result.getParamsCondition());
|
||||
assertThat(info.getHeadersCondition()).isSameAs(result.getHeadersCondition());
|
||||
@@ -75,148 +87,157 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info.getCustomCondition()).isSameAs(result.getCustomCondition());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchPatternsCondition() {
|
||||
HttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
@PathPatternsParameterizedTest
|
||||
void matchPatternsCondition(RequestMappingInfo.Builder builder) {
|
||||
|
||||
RequestMappingInfo info = paths("/foo*", "/bar").build();
|
||||
RequestMappingInfo expected = paths("/foo*").build();
|
||||
boolean useParsedPatterns = builder.build().getPathPatternsCondition() != null;
|
||||
HttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", useParsedPatterns);
|
||||
|
||||
RequestMappingInfo info = builder.paths("/foo*", "/bar").build();
|
||||
RequestMappingInfo expected = builder.paths("/foo*").build();
|
||||
|
||||
assertThat(info.getMatchingCondition(request)).isEqualTo(expected);
|
||||
|
||||
info = paths("/**", "/foo*", "/foo").build();
|
||||
expected = paths("/foo", "/foo*", "/**").build();
|
||||
info = builder.paths("/**", "/foo*", "/foo").build();
|
||||
expected = builder.paths("/foo", "/foo*", "/**").build();
|
||||
|
||||
assertThat(info.getMatchingCondition(request)).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchParamsCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
void matchParamsCondition() {
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
|
||||
request.setParameter("foo", "bar");
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
|
||||
RequestMappingInfo info = paths("/foo").params("foo=bar").build();
|
||||
RequestMappingInfo info = RequestMappingInfo.paths("/foo").params("foo=bar").build();
|
||||
RequestMappingInfo match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
|
||||
info = paths("/foo").params("foo!=bar").build();
|
||||
info = RequestMappingInfo.paths("/foo").params("foo!=bar").build();
|
||||
match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchHeadersCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
void matchHeadersCondition() {
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
|
||||
request.addHeader("foo", "bar");
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
|
||||
RequestMappingInfo info = paths("/foo").headers("foo=bar").build();
|
||||
RequestMappingInfo info = RequestMappingInfo.paths("/foo").headers("foo=bar").build();
|
||||
RequestMappingInfo match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
|
||||
info = paths("/foo").headers("foo!=bar").build();
|
||||
info = RequestMappingInfo.paths("/foo").headers("foo!=bar").build();
|
||||
match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchConsumesCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
void matchConsumesCondition() {
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
|
||||
request.setContentType("text/plain");
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
|
||||
RequestMappingInfo info = paths("/foo").consumes("text/plain").build();
|
||||
RequestMappingInfo info = RequestMappingInfo.paths("/foo").consumes("text/plain").build();
|
||||
RequestMappingInfo match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
|
||||
info = paths("/foo").consumes("application/xml").build();
|
||||
info = RequestMappingInfo.paths("/foo").consumes("application/xml").build();
|
||||
match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchProducesCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
void matchProducesCondition() {
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
|
||||
request.addHeader("Accept", "text/plain");
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
|
||||
RequestMappingInfo info = paths("/foo").produces("text/plain").build();
|
||||
RequestMappingInfo info = RequestMappingInfo.paths("/foo").produces("text/plain").build();
|
||||
RequestMappingInfo match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
|
||||
info = paths("/foo").produces("application/xml").build();
|
||||
info = RequestMappingInfo.paths("/foo").produces("application/xml").build();
|
||||
match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchCustomCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
void matchCustomCondition() {
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
|
||||
request.setParameter("foo", "bar");
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
|
||||
RequestMappingInfo info = paths("/foo").params("foo=bar").build();
|
||||
RequestMappingInfo info = RequestMappingInfo.paths("/foo").params("foo=bar").build();
|
||||
RequestMappingInfo match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNotNull();
|
||||
|
||||
info = paths("/foo").params("foo!=bar").params("foo!=bar").build();
|
||||
info = RequestMappingInfo.paths("/foo").params("foo!=bar").params("foo!=bar").build();
|
||||
match = info.getMatchingCondition(request);
|
||||
|
||||
assertThat(match).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToWithImpicitVsExplicitHttpMethodDeclaration() {
|
||||
RequestMappingInfo noMethods = paths().build();
|
||||
RequestMappingInfo oneMethod = paths().methods(GET).build();
|
||||
RequestMappingInfo oneMethodOneParam = paths().methods(GET).params("foo").build();
|
||||
void compareToWithImpicitVsExplicitHttpMethodDeclaration() {
|
||||
RequestMappingInfo noMethods = RequestMappingInfo.paths().build();
|
||||
RequestMappingInfo oneMethod = RequestMappingInfo.paths().methods(GET).build();
|
||||
RequestMappingInfo oneMethodOneParam = RequestMappingInfo.paths().methods(GET).params("foo").build();
|
||||
|
||||
Comparator<RequestMappingInfo> comparator =
|
||||
(info, otherInfo) -> info.compareTo(otherInfo, new MockHttpServletRequest());
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/", false);
|
||||
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
|
||||
Comparator<RequestMappingInfo> comparator = (info, otherInfo) -> info.compareTo(otherInfo, request);
|
||||
|
||||
List<RequestMappingInfo> list = asList(noMethods, oneMethod, oneMethodOneParam);
|
||||
Collections.shuffle(list);
|
||||
Collections.sort(list, comparator);
|
||||
list.sort(comparator);
|
||||
|
||||
assertThat(list.get(0)).isEqualTo(oneMethodOneParam);
|
||||
assertThat(list.get(1)).isEqualTo(oneMethod);
|
||||
assertThat(list.get(2)).isEqualTo(noMethods);
|
||||
}
|
||||
|
||||
@Test // SPR-14383
|
||||
public void compareToWithHttpHeadMapping() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
@Test
|
||||
// SPR-14383
|
||||
void compareToWithHttpHeadMapping() {
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/", false);
|
||||
request.setMethod("HEAD");
|
||||
request.addHeader("Accept", "application/json");
|
||||
|
||||
RequestMappingInfo noMethods = paths().build();
|
||||
RequestMappingInfo getMethod = paths().methods(GET).produces("application/json").build();
|
||||
RequestMappingInfo headMethod = paths().methods(HEAD).build();
|
||||
RequestMappingInfo noMethods = RequestMappingInfo.paths().build();
|
||||
RequestMappingInfo getMethod = RequestMappingInfo.paths().methods(GET).produces("application/json").build();
|
||||
RequestMappingInfo headMethod = RequestMappingInfo.paths().methods(HEAD).build();
|
||||
|
||||
Comparator<RequestMappingInfo> comparator = (info, otherInfo) -> info.compareTo(otherInfo, request);
|
||||
|
||||
List<RequestMappingInfo> list = asList(noMethods, getMethod, headMethod);
|
||||
Collections.shuffle(list);
|
||||
Collections.sort(list, comparator);
|
||||
list.sort(comparator);
|
||||
|
||||
assertThat(list.get(0)).isEqualTo(headMethod);
|
||||
assertThat(list.get(1)).isEqualTo(getMethod);
|
||||
assertThat(list.get(2)).isEqualTo(noMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals() {
|
||||
RequestMappingInfo info1 = paths("/foo").methods(GET)
|
||||
@PathPatternsParameterizedTest
|
||||
void equalsMethod(RequestMappingInfo.Builder infoBuilder) {
|
||||
RequestMappingInfo info1 = infoBuilder.paths("/foo").methods(GET)
|
||||
.params("foo=bar", "customFoo=customBar").headers("foo=bar")
|
||||
.consumes("text/plain").produces("text/plain")
|
||||
.build();
|
||||
|
||||
RequestMappingInfo info2 = paths("/foo").methods(GET)
|
||||
RequestMappingInfo info2 = infoBuilder.paths("/foo").methods(GET)
|
||||
.params("foo=bar", "customFoo=customBar").headers("foo=bar")
|
||||
.consumes("text/plain").produces("text/plain")
|
||||
.build();
|
||||
@@ -224,7 +245,7 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info2).isEqualTo(info1);
|
||||
assertThat(info2.hashCode()).isEqualTo(info1.hashCode());
|
||||
|
||||
info2 = paths("/foo", "/NOOOOOO").methods(GET)
|
||||
info2 = infoBuilder.paths("/foo", "/NOOOOOO").methods(GET)
|
||||
.params("foo=bar", "customFoo=customBar").headers("foo=bar")
|
||||
.consumes("text/plain").produces("text/plain")
|
||||
.build();
|
||||
@@ -232,7 +253,7 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info1.equals(info2)).isFalse();
|
||||
assertThat(info2.hashCode()).isNotEqualTo((long) info1.hashCode());
|
||||
|
||||
info2 = paths("/foo").methods(GET, RequestMethod.POST)
|
||||
info2 = infoBuilder.paths("/foo").methods(GET, RequestMethod.POST)
|
||||
.params("foo=bar", "customFoo=customBar").headers("foo=bar")
|
||||
.consumes("text/plain").produces("text/plain")
|
||||
.build();
|
||||
@@ -240,7 +261,7 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info1.equals(info2)).isFalse();
|
||||
assertThat(info2.hashCode()).isNotEqualTo((long) info1.hashCode());
|
||||
|
||||
info2 = paths("/foo").methods(GET)
|
||||
info2 = infoBuilder.paths("/foo").methods(GET)
|
||||
.params("/NOOOOOO", "customFoo=customBar").headers("foo=bar")
|
||||
.consumes("text/plain").produces("text/plain")
|
||||
.build();
|
||||
@@ -248,7 +269,7 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info1.equals(info2)).isFalse();
|
||||
assertThat(info2.hashCode()).isNotEqualTo((long) info1.hashCode());
|
||||
|
||||
info2 = paths("/foo").methods(GET)
|
||||
info2 = infoBuilder.paths("/foo").methods(GET)
|
||||
.params("foo=bar", "customFoo=customBar").headers("/NOOOOOO")
|
||||
.consumes("text/plain").produces("text/plain")
|
||||
.build();
|
||||
@@ -256,7 +277,7 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info1.equals(info2)).isFalse();
|
||||
assertThat(info2.hashCode()).isNotEqualTo((long) info1.hashCode());
|
||||
|
||||
info2 = paths("/foo").methods(GET)
|
||||
info2 = infoBuilder.paths("/foo").methods(GET)
|
||||
.params("foo=bar", "customFoo=customBar").headers("foo=bar")
|
||||
.consumes("text/NOOOOOO").produces("text/plain")
|
||||
.build();
|
||||
@@ -264,7 +285,7 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info1.equals(info2)).isFalse();
|
||||
assertThat(info2.hashCode()).isNotEqualTo((long) info1.hashCode());
|
||||
|
||||
info2 = paths("/foo").methods(GET)
|
||||
info2 = infoBuilder.paths("/foo").methods(GET)
|
||||
.params("foo=bar", "customFoo=customBar").headers("foo=bar")
|
||||
.consumes("text/plain").produces("text/NOOOOOO")
|
||||
.build();
|
||||
@@ -272,7 +293,7 @@ public class RequestMappingInfoTests {
|
||||
assertThat(info1.equals(info2)).isFalse();
|
||||
assertThat(info2.hashCode()).isNotEqualTo((long) info1.hashCode());
|
||||
|
||||
info2 = paths("/foo").methods(GET)
|
||||
info2 = infoBuilder.paths("/foo").methods(GET)
|
||||
.params("foo=bar", "customFoo=NOOOOOO").headers("foo=bar")
|
||||
.consumes("text/plain").produces("text/plain")
|
||||
.build();
|
||||
@@ -282,16 +303,16 @@ public class RequestMappingInfoTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preFlightRequest() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/foo");
|
||||
void preFlightRequest() {
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("OPTIONS", "/foo", false);
|
||||
request.addHeader(HttpHeaders.ORIGIN, "https://domain.com");
|
||||
request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST");
|
||||
|
||||
RequestMappingInfo info = paths("/foo").methods(RequestMethod.POST).build();
|
||||
RequestMappingInfo info = RequestMappingInfo.paths("/foo").methods(RequestMethod.POST).build();
|
||||
RequestMappingInfo match = info.getMatchingCondition(request);
|
||||
assertThat(match).isNotNull();
|
||||
|
||||
info = paths("/foo").methods(RequestMethod.OPTIONS).build();
|
||||
info = RequestMappingInfo.paths("/foo").methods(RequestMethod.OPTIONS).build();
|
||||
match = info.getMatchingCondition(request);
|
||||
assertThat(match).as("Pre-flight should match the ACCESS_CONTROL_REQUEST_METHOD").isNull();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,6 +20,7 @@ import javax.servlet.ServletException;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -29,6 +30,7 @@ import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
|
||||
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
||||
import org.springframework.web.testfixture.servlet.MockServletConfig;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -44,6 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public abstract class AbstractServletHandlerMethodTests {
|
||||
|
||||
@Nullable
|
||||
private DispatcherServlet servlet;
|
||||
|
||||
|
||||
@@ -57,49 +60,54 @@ public abstract class AbstractServletHandlerMethodTests {
|
||||
this.servlet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a DispatcherServlet instance registering zero or more controller classes.
|
||||
*/
|
||||
protected WebApplicationContext initServletWithControllers(final Class<?>... controllerClasses)
|
||||
throws ServletException {
|
||||
protected WebApplicationContext initDispatcherServlet(
|
||||
Class<?> controllerClass, boolean usePathPatterns) throws ServletException {
|
||||
|
||||
return initServlet(null, controllerClasses);
|
||||
return initDispatcherServlet(controllerClass, usePathPatterns, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a DispatcherServlet instance registering zero or more controller classes
|
||||
* and also providing additional bean definitions through a callback.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
protected WebApplicationContext initServlet(
|
||||
final ApplicationContextInitializer<GenericWebApplicationContext> initializer,
|
||||
final Class<?>... controllerClasses) throws ServletException {
|
||||
WebApplicationContext initDispatcherServlet(
|
||||
@Nullable Class<?> controllerClass, boolean usePathPatterns,
|
||||
@Nullable ApplicationContextInitializer<GenericWebApplicationContext> initializer)
|
||||
throws ServletException {
|
||||
|
||||
final GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
|
||||
servlet = new DispatcherServlet() {
|
||||
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) {
|
||||
for (Class<?> clazz : controllerClasses) {
|
||||
wac.registerBeanDefinition(clazz.getSimpleName(), new RootBeanDefinition(clazz));
|
||||
}
|
||||
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("removeSemicolonContent", "false");
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
wac.registerBeanDefinition("handlerAdapter",
|
||||
new RootBeanDefinition(RequestMappingHandlerAdapter.class));
|
||||
wac.registerBeanDefinition("requestMappingResolver",
|
||||
new RootBeanDefinition(ExceptionHandlerExceptionResolver.class));
|
||||
wac.registerBeanDefinition("responseStatusResolver",
|
||||
new RootBeanDefinition(ResponseStatusExceptionResolver.class));
|
||||
wac.registerBeanDefinition("defaultResolver",
|
||||
new RootBeanDefinition(DefaultHandlerExceptionResolver.class));
|
||||
if (controllerClass != null) {
|
||||
wac.registerBeanDefinition(
|
||||
controllerClass.getSimpleName(), new RootBeanDefinition(controllerClass));
|
||||
}
|
||||
|
||||
if (initializer != null) {
|
||||
initializer.initialize(wac);
|
||||
}
|
||||
|
||||
if (!wac.containsBeanDefinition("handlerMapping")) {
|
||||
BeanDefinition def = register("handlerMapping", RequestMappingHandlerMapping.class, wac);
|
||||
def.getPropertyValues().add("removeSemicolonContent", "false");
|
||||
}
|
||||
|
||||
BeanDefinition mappingDef = wac.getBeanDefinition("handlerMapping");
|
||||
if (usePathPatterns && !mappingDef.hasAttribute("patternParser")) {
|
||||
BeanDefinition parserDef = register("parser", PathPatternParser.class, wac);
|
||||
mappingDef.getPropertyValues().add("patternParser", parserDef);
|
||||
}
|
||||
|
||||
register("handlerAdapter", RequestMappingHandlerAdapter.class, wac);
|
||||
register("requestMappingResolver", ExceptionHandlerExceptionResolver.class, wac);
|
||||
register("responseStatusResolver", ResponseStatusExceptionResolver.class, wac);
|
||||
register("defaultResolver", DefaultHandlerExceptionResolver.class, wac);
|
||||
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
@@ -110,4 +118,13 @@ public abstract class AbstractServletHandlerMethodTests {
|
||||
return wac;
|
||||
}
|
||||
|
||||
private BeanDefinition register(String beanName, Class<?> beanType, GenericWebApplicationContext wac) {
|
||||
if (wac.containsBeanDefinition(beanName)) {
|
||||
return wac.getBeanDefinition(beanName);
|
||||
}
|
||||
RootBeanDefinition beanDef = new RootBeanDefinition(beanType);
|
||||
wac.registerBeanDefinition(beanName, beanDef);
|
||||
return beanDef;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,11 +21,13 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
@@ -33,6 +35,8 @@ import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.RequestPath;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
@@ -44,14 +48,11 @@ import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
|
||||
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
@@ -62,21 +63,12 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
* @author Sebastien Deleuze
|
||||
* @author Sam Brannen
|
||||
* @author Nicolas Labrot
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class CrossOriginTests {
|
||||
class CrossOriginTests {
|
||||
|
||||
private final TestRequestMappingInfoHandlerMapping handlerMapping = new TestRequestMappingInfoHandlerMapping();
|
||||
|
||||
private final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
private final String optionsHandler = "org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping$HttpOptionsHandler#handle()";
|
||||
|
||||
private final String corsPreflightHandler = "org.springframework.web.servlet.handler.AbstractHandlerMapping$PreFlightHandler";
|
||||
|
||||
|
||||
@BeforeEach
|
||||
@SuppressWarnings("resource")
|
||||
public void setup() {
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<TestRequestMappingInfoHandlerMapping> pathPatternsArguments() {
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("myOrigin", "https://example.com");
|
||||
@@ -84,234 +76,252 @@ public class CrossOriginTests {
|
||||
wac.registerSingleton("ppc", PropertySourcesPlaceholderConfigurer.class);
|
||||
wac.refresh();
|
||||
|
||||
this.handlerMapping.setRemoveSemicolonContent(false);
|
||||
wac.getAutowireCapableBeanFactory().initializeBean(this.handlerMapping, "hm");
|
||||
TestRequestMappingInfoHandlerMapping mapping1 = new TestRequestMappingInfoHandlerMapping();
|
||||
mapping1.setPatternParser(new PathPatternParser());
|
||||
wac.getAutowireCapableBeanFactory().initializeBean(mapping1, "mapping1");
|
||||
|
||||
TestRequestMappingInfoHandlerMapping mapping2 = new TestRequestMappingInfoHandlerMapping();
|
||||
wac.getAutowireCapableBeanFactory().initializeBean(mapping2, "mapping2");
|
||||
|
||||
return Stream.of(mapping1, mapping2);
|
||||
}
|
||||
|
||||
|
||||
private final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.request.setMethod("GET");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain.com/");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void noAnnotationWithoutOrigin() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void noAnnotationWithoutOrigin(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/no");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
assertThat(getCorsConfiguration(chain, false)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noAnnotationWithAccessControlRequestMethod() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void noAnnotationWithAccessControlRequestMethod(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/no");
|
||||
request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
assertThat(chain.getHandler().toString()).isEqualTo(optionsHandler);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler().toString())
|
||||
.endsWith("RequestMappingInfoHandlerMapping$HttpOptionsHandler#handle()");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noAnnotationWithPreflightRequest() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void noAnnotationWithPreflightRequest(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/no");
|
||||
request.addHeader(HttpHeaders.ORIGIN, "https://domain.com/");
|
||||
request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
assertThat(chain.getHandler().getClass().getName()).isEqualTo(corsPreflightHandler);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
assertThat(chain).isNotNull();
|
||||
assertThat(chain.getHandler().getClass().getName()).endsWith("AbstractHandlerMapping$PreFlightHandler");
|
||||
}
|
||||
|
||||
@Test // SPR-12931
|
||||
public void noAnnotationWithOrigin() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest // SPR-12931
|
||||
void noAnnotationWithOrigin(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setRequestURI("/no");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
assertThat(getCorsConfiguration(chain, false)).isNull();
|
||||
}
|
||||
|
||||
@Test // SPR-12931
|
||||
public void noAnnotationPostWithOrigin() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest // SPR-12931
|
||||
void noAnnotationPostWithOrigin(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setMethod("POST");
|
||||
this.request.setRequestURI("/no");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
assertThat(getCorsConfiguration(chain, false)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultAnnotation() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void defaultAnnotation(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setRequestURI("/default");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"GET"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat(config.getAllowedMethods()).containsExactly("GET");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isNull();
|
||||
assertThat(config.getAllowedHeaders().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat(config.getAllowedHeaders()).containsExactly("*");
|
||||
assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue();
|
||||
assertThat(config.getMaxAge()).isEqualTo(new Long(1800));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customized() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void customized(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setRequestURI("/customized");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"DELETE"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"https://site1.com", "https://site2.com"});
|
||||
assertThat(config.getAllowedHeaders().toArray()).isEqualTo(new String[] {"header1", "header2"});
|
||||
assertThat(config.getExposedHeaders().toArray()).isEqualTo(new String[] {"header3", "header4"});
|
||||
assertThat(config.getAllowedMethods()).containsExactly("DELETE");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("https://site1.com", "https://site2.com");
|
||||
assertThat(config.getAllowedHeaders()).containsExactly("header1", "header2");
|
||||
assertThat(config.getExposedHeaders()).containsExactly("header3", "header4");
|
||||
assertThat(config.getMaxAge()).isEqualTo(new Long(123));
|
||||
assertThat((boolean) config.getAllowCredentials()).isFalse();
|
||||
assertThat(config.getAllowCredentials()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customOriginDefinedViaValueAttribute() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void customOriginDefinedViaValueAttribute(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setRequestURI("/customOrigin");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedOrigins()).isEqualTo(Arrays.asList("https://example.com"));
|
||||
assertThat(config.getAllowedOrigins()).isEqualTo(Collections.singletonList("https://example.com"));
|
||||
assertThat(config.getAllowCredentials()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customOriginDefinedViaPlaceholder() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void customOriginDefinedViaPlaceholder(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setRequestURI("/someOrigin");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedOrigins()).isEqualTo(Arrays.asList("https://example.com"));
|
||||
assertThat(config.getAllowedOrigins()).isEqualTo(Collections.singletonList("https://example.com"));
|
||||
assertThat(config.getAllowCredentials()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bogusAllowCredentialsValue() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void bogusAllowCredentialsValue(TestRequestMappingInfoHandlerMapping mapping) {
|
||||
assertThatIllegalStateException().isThrownBy(() ->
|
||||
this.handlerMapping.registerHandler(new MethodLevelControllerWithBogusAllowCredentialsValue()))
|
||||
mapping.registerHandler(new MethodLevelControllerWithBogusAllowCredentialsValue()))
|
||||
.withMessageContaining("@CrossOrigin's allowCredentials")
|
||||
.withMessageContaining("current value is [bogus]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classLevel() throws Exception {
|
||||
this.handlerMapping.registerHandler(new ClassLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void classLevel(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new ClassLevelController());
|
||||
|
||||
this.request.setRequestURI("/foo");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"GET"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat((boolean) config.getAllowCredentials()).isFalse();
|
||||
assertThat(config.getAllowedMethods()).containsExactly("GET");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isFalse();
|
||||
|
||||
this.request.setRequestURI("/bar");
|
||||
chain = this.handlerMapping.getHandler(request);
|
||||
chain = mapping.getHandler(request);
|
||||
config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"GET"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat((boolean) config.getAllowCredentials()).isFalse();
|
||||
assertThat(config.getAllowedMethods()).containsExactly("GET");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isFalse();
|
||||
|
||||
this.request.setRequestURI("/baz");
|
||||
chain = this.handlerMapping.getHandler(request);
|
||||
chain = mapping.getHandler(request);
|
||||
config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"GET"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat((boolean) config.getAllowCredentials()).isTrue();
|
||||
assertThat(config.getAllowedMethods()).containsExactly("GET");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isTrue();
|
||||
}
|
||||
|
||||
@Test // SPR-13468
|
||||
public void classLevelComposedAnnotation() throws Exception {
|
||||
this.handlerMapping.registerHandler(new ClassLevelMappingWithComposedAnnotation());
|
||||
@PathPatternsParameterizedTest // SPR-13468
|
||||
void classLevelComposedAnnotation(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new ClassLevelMappingWithComposedAnnotation());
|
||||
|
||||
this.request.setRequestURI("/foo");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"GET"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"http://www.foo.example/"});
|
||||
assertThat((boolean) config.getAllowCredentials()).isTrue();
|
||||
assertThat(config.getAllowedMethods()).containsExactly("GET");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("http://www.foo.example/");
|
||||
assertThat(config.getAllowCredentials()).isTrue();
|
||||
}
|
||||
|
||||
@Test // SPR-13468
|
||||
public void methodLevelComposedAnnotation() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelMappingWithComposedAnnotation());
|
||||
@PathPatternsParameterizedTest // SPR-13468
|
||||
void methodLevelComposedAnnotation(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelMappingWithComposedAnnotation());
|
||||
|
||||
this.request.setRequestURI("/foo");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"GET"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"http://www.foo.example/"});
|
||||
assertThat((boolean) config.getAllowCredentials()).isTrue();
|
||||
assertThat(config.getAllowedMethods()).containsExactly("GET");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("http://www.foo.example/");
|
||||
assertThat(config.getAllowCredentials()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preFlightRequest() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void preFlightRequest(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setMethod("OPTIONS");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.setRequestURI("/default");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, true);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"GET"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat(config.getAllowedMethods()).containsExactly("GET");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isNull();
|
||||
assertThat(config.getAllowedHeaders().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat(config.getAllowedHeaders()).containsExactly("*");
|
||||
assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue();
|
||||
assertThat(config.getMaxAge()).isEqualTo(new Long(1800));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ambiguousHeaderPreFlightRequest() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void ambiguousHeaderPreFlightRequest(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setMethod("OPTIONS");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "header1");
|
||||
this.request.setRequestURI("/ambiguous-header");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, true);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat(config.getAllowedHeaders().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat((boolean) config.getAllowCredentials()).isTrue();
|
||||
assertThat(config.getAllowedMethods()).containsExactly("*");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowedHeaders()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isTrue();
|
||||
assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue();
|
||||
assertThat(config.getMaxAge()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ambiguousProducesPreFlightRequest() throws Exception {
|
||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||
@PathPatternsParameterizedTest
|
||||
void ambiguousProducesPreFlightRequest(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
mapping.registerHandler(new MethodLevelController());
|
||||
this.request.setMethod("OPTIONS");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.setRequestURI("/ambiguous-produces");
|
||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
CorsConfiguration config = getCorsConfiguration(chain, true);
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getAllowedMethods().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat(config.getAllowedOrigins().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat(config.getAllowedHeaders().toArray()).isEqualTo(new String[] {"*"});
|
||||
assertThat((boolean) config.getAllowCredentials()).isTrue();
|
||||
assertThat(config.getAllowedMethods()).containsExactly("*");
|
||||
assertThat(config.getAllowedOrigins()).containsExactly("*");
|
||||
assertThat(config.getAllowedHeaders()).containsExactly("*");
|
||||
assertThat(config.getAllowCredentials()).isTrue();
|
||||
assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue();
|
||||
assertThat(config.getMaxAge()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preFlightRequestWithoutRequestMethodHeader() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void preFlightRequestWithoutRequestMethodHeader(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/default");
|
||||
request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
|
||||
assertThat(this.handlerMapping.getHandler(request)).isNull();
|
||||
assertThat(mapping.getHandler(request)).isNull();
|
||||
}
|
||||
|
||||
|
||||
private CorsConfiguration getCorsConfiguration(HandlerExecutionChain chain, boolean isPreFlightRequest) {
|
||||
@Nullable
|
||||
private CorsConfiguration getCorsConfiguration(@Nullable HandlerExecutionChain chain, boolean isPreFlightRequest) {
|
||||
assertThat(chain).isNotNull();
|
||||
if (isPreFlightRequest) {
|
||||
Object handler = chain.getHandler();
|
||||
assertThat(handler.getClass().getSimpleName().equals("PreFlightHandler")).isTrue();
|
||||
@@ -334,6 +344,7 @@ public class CrossOriginTests {
|
||||
|
||||
|
||||
@Controller
|
||||
@SuppressWarnings("unused")
|
||||
private static class MethodLevelController {
|
||||
|
||||
@GetMapping("/no")
|
||||
@@ -399,6 +410,7 @@ public class CrossOriginTests {
|
||||
|
||||
|
||||
@Controller
|
||||
@SuppressWarnings("unused")
|
||||
private static class MethodLevelControllerWithBogusAllowCredentialsValue {
|
||||
|
||||
@CrossOrigin(allowCredentials = "bogus")
|
||||
@@ -462,7 +474,7 @@ public class CrossOriginTests {
|
||||
|
||||
private static class TestRequestMappingInfoHandlerMapping extends RequestMappingHandlerMapping {
|
||||
|
||||
public void registerHandler(Object handler) {
|
||||
void registerHandler(Object handler) {
|
||||
super.detectHandlerMethods(handler);
|
||||
}
|
||||
|
||||
@@ -475,18 +487,33 @@ public class CrossOriginTests {
|
||||
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
RequestMapping annotation = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
|
||||
if (annotation != null) {
|
||||
return new RequestMappingInfo(
|
||||
new PatternsRequestCondition(annotation.value(), getUrlPathHelper(), getPathMatcher(), true, true),
|
||||
new RequestMethodsRequestCondition(annotation.method()),
|
||||
new ParamsRequestCondition(annotation.params()),
|
||||
new HeadersRequestCondition(annotation.headers()),
|
||||
new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),
|
||||
new ProducesRequestCondition(annotation.produces(), annotation.headers()), null);
|
||||
RequestMappingInfo.BuilderConfiguration options = new RequestMappingInfo.BuilderConfiguration();
|
||||
if (getPatternParser() != null) {
|
||||
options.setPatternParser(getPatternParser());
|
||||
}
|
||||
return RequestMappingInfo.paths(annotation.value())
|
||||
.methods(annotation.method())
|
||||
.params(annotation.params())
|
||||
.headers(annotation.headers())
|
||||
.consumes(annotation.consumes())
|
||||
.produces(annotation.produces())
|
||||
.options(options)
|
||||
.build();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String initLookupPath(HttpServletRequest request) {
|
||||
// At runtime this is done by the DispatcherServlet
|
||||
if (getPatternParser() != null) {
|
||||
RequestPath requestPath = ServletRequestPathUtils.parseAndCache(request);
|
||||
return requestPath.pathWithinApplication().value();
|
||||
}
|
||||
return super.initLookupPath(request);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -46,9 +48,12 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.method.HandlerTypePredicate;
|
||||
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
|
||||
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -61,41 +66,49 @@ import static org.mockito.Mockito.mock;
|
||||
*/
|
||||
public class RequestMappingHandlerMappingTests {
|
||||
|
||||
private final StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<Arguments> pathPatternsArguments() {
|
||||
RequestMappingHandlerMapping mapping1 = new RequestMappingHandlerMapping();
|
||||
StaticWebApplicationContext wac1 = new StaticWebApplicationContext();
|
||||
mapping1.setPatternParser(new PathPatternParser());
|
||||
mapping1.setApplicationContext(wac1);
|
||||
|
||||
private final RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
|
||||
{
|
||||
this.handlerMapping.setApplicationContext(wac);
|
||||
RequestMappingHandlerMapping mapping2 = new RequestMappingHandlerMapping();
|
||||
StaticWebApplicationContext wac2 = new StaticWebApplicationContext();
|
||||
mapping2.setApplicationContext(wac2);
|
||||
|
||||
return Stream.of(Arguments.of(mapping1, wac1), Arguments.of(mapping2, wac2));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void useRegisteredSuffixPatternMatch() {
|
||||
assertThat(this.handlerMapping.useSuffixPatternMatch()).isFalse();
|
||||
assertThat(this.handlerMapping.useRegisteredSuffixPatternMatch()).isFalse();
|
||||
void useRegisteredSuffixPatternMatch() {
|
||||
|
||||
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
|
||||
handlerMapping.setApplicationContext(new StaticWebApplicationContext());
|
||||
|
||||
Map<String, MediaType> fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
|
||||
PathExtensionContentNegotiationStrategy strategy = new PathExtensionContentNegotiationStrategy(fileExtensions);
|
||||
ContentNegotiationManager manager = new ContentNegotiationManager(strategy);
|
||||
|
||||
this.handlerMapping.setContentNegotiationManager(manager);
|
||||
this.handlerMapping.setUseRegisteredSuffixPatternMatch(true);
|
||||
this.handlerMapping.afterPropertiesSet();
|
||||
handlerMapping.setContentNegotiationManager(manager);
|
||||
handlerMapping.setUseRegisteredSuffixPatternMatch(true);
|
||||
handlerMapping.afterPropertiesSet();
|
||||
|
||||
assertThat(this.handlerMapping.useSuffixPatternMatch()).isTrue();
|
||||
assertThat(this.handlerMapping.useRegisteredSuffixPatternMatch()).isTrue();
|
||||
assertThat(this.handlerMapping.getFileExtensions()).isEqualTo(Collections.singletonList("json"));
|
||||
assertThat(handlerMapping.useSuffixPatternMatch()).isTrue();
|
||||
assertThat(handlerMapping.useRegisteredSuffixPatternMatch()).isTrue();
|
||||
assertThat(handlerMapping.getFileExtensions()).isEqualTo(Collections.singletonList("json"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useRegisteredSuffixPatternMatchInitialization() {
|
||||
void useRegisteredSuffixPatternMatchInitialization() {
|
||||
Map<String, MediaType> fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
|
||||
PathExtensionContentNegotiationStrategy strategy = new PathExtensionContentNegotiationStrategy(fileExtensions);
|
||||
ContentNegotiationManager manager = new ContentNegotiationManager(strategy);
|
||||
|
||||
final Set<String> extensions = new HashSet<>();
|
||||
|
||||
RequestMappingHandlerMapping hm = new RequestMappingHandlerMapping() {
|
||||
RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping() {
|
||||
@Override
|
||||
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
extensions.addAll(getFileExtensions());
|
||||
@@ -103,76 +116,99 @@ public class RequestMappingHandlerMappingTests {
|
||||
}
|
||||
};
|
||||
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.registerSingleton("testController", ComposedAnnotationController.class);
|
||||
wac.refresh();
|
||||
|
||||
hm.setContentNegotiationManager(manager);
|
||||
hm.setUseRegisteredSuffixPatternMatch(true);
|
||||
hm.setApplicationContext(wac);
|
||||
hm.afterPropertiesSet();
|
||||
mapping.setContentNegotiationManager(manager);
|
||||
mapping.setUseRegisteredSuffixPatternMatch(true);
|
||||
mapping.setApplicationContext(wac);
|
||||
mapping.afterPropertiesSet();
|
||||
|
||||
assertThat(extensions).isEqualTo(Collections.singleton("json"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useSuffixPatternMatch() {
|
||||
assertThat(this.handlerMapping.useSuffixPatternMatch()).isFalse();
|
||||
void suffixPatternMatchSettings() {
|
||||
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
|
||||
|
||||
this.handlerMapping.setUseRegisteredSuffixPatternMatch(false);
|
||||
assertThat(this.handlerMapping.useSuffixPatternMatch())
|
||||
.as("'false' registeredSuffixPatternMatch shouldn't impact suffixPatternMatch").isFalse();
|
||||
assertThat(handlerMapping.useSuffixPatternMatch()).isFalse();
|
||||
assertThat(handlerMapping.useRegisteredSuffixPatternMatch()).isFalse();
|
||||
|
||||
this.handlerMapping.setUseRegisteredSuffixPatternMatch(true);
|
||||
assertThat(this.handlerMapping.useSuffixPatternMatch())
|
||||
.as("'true' registeredSuffixPatternMatch should enable suffixPatternMatch").isTrue();
|
||||
handlerMapping.setUseRegisteredSuffixPatternMatch(false);
|
||||
assertThat(handlerMapping.useSuffixPatternMatch())
|
||||
.as("'false' registeredSuffixPatternMatch shouldn't impact suffixPatternMatch")
|
||||
.isFalse();
|
||||
|
||||
handlerMapping.setUseRegisteredSuffixPatternMatch(true);
|
||||
assertThat(handlerMapping.useSuffixPatternMatch())
|
||||
.as("'true' registeredSuffixPatternMatch should enable suffixPatternMatch")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveEmbeddedValuesInPatterns() {
|
||||
this.handlerMapping.setEmbeddedValueResolver(
|
||||
@PathPatternsParameterizedTest
|
||||
void resolveEmbeddedValuesInPatterns(RequestMappingHandlerMapping mapping) {
|
||||
|
||||
mapping.setEmbeddedValueResolver(
|
||||
value -> "/${pattern}/bar".equals(value) ? "/foo/bar" : value
|
||||
);
|
||||
|
||||
String[] patterns = new String[] { "/foo", "/${pattern}/bar" };
|
||||
String[] result = this.handlerMapping.resolveEmbeddedValuesInPatterns(patterns);
|
||||
String[] result = mapping.resolveEmbeddedValuesInPatterns(patterns);
|
||||
|
||||
assertThat(result).isEqualTo(new String[] { "/foo", "/foo/bar" });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathPrefix() throws NoSuchMethodException {
|
||||
this.handlerMapping.setEmbeddedValueResolver(value -> "/${prefix}".equals(value) ? "/api" : value);
|
||||
this.handlerMapping.setPathPrefixes(Collections.singletonMap(
|
||||
@PathPatternsParameterizedTest
|
||||
void pathPrefix(RequestMappingHandlerMapping mapping) throws Exception {
|
||||
|
||||
mapping.setEmbeddedValueResolver(value -> "/${prefix}".equals(value) ? "/api" : value);
|
||||
mapping.setPathPrefixes(Collections.singletonMap(
|
||||
"/${prefix}", HandlerTypePredicate.forAnnotation(RestController.class)));
|
||||
mapping.afterPropertiesSet();
|
||||
|
||||
Method method = UserController.class.getMethod("getUser");
|
||||
RequestMappingInfo info = this.handlerMapping.getMappingForMethod(method, UserController.class);
|
||||
RequestMappingInfo info = mapping.getMappingForMethod(method, UserController.class);
|
||||
|
||||
assertThat(info).isNotNull();
|
||||
assertThat(info.getPatternsCondition().getPatterns()).isEqualTo(Collections.singleton("/api/user/{id}"));
|
||||
assertThat(info.getPatternValues()).isEqualTo(Collections.singleton("/api/user/{id}"));
|
||||
}
|
||||
|
||||
@Test // gh-23907
|
||||
public void pathPrefixPreservesPathMatchingSettings() throws NoSuchMethodException {
|
||||
this.handlerMapping.setUseSuffixPatternMatch(false);
|
||||
this.handlerMapping.setPathPrefixes(Collections.singletonMap("/api", HandlerTypePredicate.forAnyHandlerType()));
|
||||
this.handlerMapping.afterPropertiesSet();
|
||||
@PathPatternsParameterizedTest // gh-23907
|
||||
void pathPrefixPreservesPathMatchingSettings(RequestMappingHandlerMapping mapping) throws Exception {
|
||||
mapping.setPathPrefixes(Collections.singletonMap("/api", HandlerTypePredicate.forAnyHandlerType()));
|
||||
mapping.afterPropertiesSet();
|
||||
|
||||
Method method = ComposedAnnotationController.class.getMethod("get");
|
||||
RequestMappingInfo info = this.handlerMapping.getMappingForMethod(method, ComposedAnnotationController.class);
|
||||
RequestMappingInfo info = mapping.getMappingForMethod(method, ComposedAnnotationController.class);
|
||||
|
||||
assertThat(info).isNotNull();
|
||||
assertThat(info.getActivePatternsCondition()).isNotNull();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/get");
|
||||
assertThat(info.getPatternsCondition().getMatchingCondition(request)).isNotNull();
|
||||
initRequestPath(mapping, request);
|
||||
assertThat(info.getActivePatternsCondition().getMatchingCondition(request)).isNotNull();
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/api/get.pdf");
|
||||
assertThat(info.getPatternsCondition().getMatchingCondition(request)).isNull();
|
||||
initRequestPath(mapping, request);
|
||||
assertThat(info.getActivePatternsCondition().getMatchingCondition(request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveRequestMappingViaComposedAnnotation() throws Exception {
|
||||
RequestMappingInfo info = assertComposedAnnotationMapping("postJson", "/postJson", RequestMethod.POST);
|
||||
private void initRequestPath(RequestMappingHandlerMapping mapping, MockHttpServletRequest request) {
|
||||
PathPatternParser parser = mapping.getPatternParser();
|
||||
if (parser != null) {
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
}
|
||||
else {
|
||||
mapping.getUrlPathHelper().resolveAndCacheLookupPath(request);
|
||||
}
|
||||
}
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void resolveRequestMappingViaComposedAnnotation(RequestMappingHandlerMapping mapping) {
|
||||
|
||||
RequestMappingInfo info = assertComposedAnnotationMapping(
|
||||
mapping, "postJson", "/postJson", RequestMethod.POST);
|
||||
|
||||
assertThat(info.getConsumesCondition().getConsumableMediaTypes().iterator().next().toString())
|
||||
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
|
||||
@@ -181,68 +217,72 @@ public class RequestMappingHandlerMappingTests {
|
||||
}
|
||||
|
||||
@Test // SPR-14988
|
||||
public void getMappingOverridesConsumesFromTypeLevelAnnotation() throws Exception {
|
||||
void getMappingOverridesConsumesFromTypeLevelAnnotation() throws Exception {
|
||||
RequestMappingInfo requestMappingInfo = assertComposedAnnotationMapping(RequestMethod.POST);
|
||||
|
||||
ConsumesRequestCondition condition = requestMappingInfo.getConsumesCondition();
|
||||
assertThat(condition.getConsumableMediaTypes()).isEqualTo(Collections.singleton(MediaType.APPLICATION_XML));
|
||||
}
|
||||
|
||||
@Test // gh-22010
|
||||
public void consumesWithOptionalRequestBody() {
|
||||
this.wac.registerSingleton("testController", ComposedAnnotationController.class);
|
||||
this.wac.refresh();
|
||||
this.handlerMapping.afterPropertiesSet();
|
||||
RequestMappingInfo info = this.handlerMapping.getHandlerMethods().keySet().stream()
|
||||
.filter(i -> i.getPatternsCondition().getPatterns().equals(Collections.singleton("/post")))
|
||||
@PathPatternsParameterizedTest // gh-22010
|
||||
void consumesWithOptionalRequestBody(RequestMappingHandlerMapping mapping, StaticWebApplicationContext wac) {
|
||||
wac.registerSingleton("testController", ComposedAnnotationController.class);
|
||||
wac.refresh();
|
||||
mapping.afterPropertiesSet();
|
||||
RequestMappingInfo result = mapping.getHandlerMethods().keySet().stream()
|
||||
.filter(info -> info.getPatternValues().equals(Collections.singleton("/post")))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new AssertionError("No /post"));
|
||||
|
||||
assertThat(info.getConsumesCondition().isBodyRequired()).isFalse();
|
||||
assertThat(result.getConsumesCondition().isBodyRequired()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMapping() throws Exception {
|
||||
void getMapping() throws Exception {
|
||||
assertComposedAnnotationMapping(RequestMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postMapping() throws Exception {
|
||||
void postMapping() throws Exception {
|
||||
assertComposedAnnotationMapping(RequestMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putMapping() throws Exception {
|
||||
void putMapping() throws Exception {
|
||||
assertComposedAnnotationMapping(RequestMethod.PUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteMapping() throws Exception {
|
||||
void deleteMapping() throws Exception {
|
||||
assertComposedAnnotationMapping(RequestMethod.DELETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchMapping() throws Exception {
|
||||
void patchMapping() throws Exception {
|
||||
assertComposedAnnotationMapping(RequestMethod.PATCH);
|
||||
}
|
||||
|
||||
private RequestMappingInfo assertComposedAnnotationMapping(RequestMethod requestMethod) throws Exception {
|
||||
|
||||
RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
|
||||
mapping.setApplicationContext(new StaticWebApplicationContext());
|
||||
|
||||
String methodName = requestMethod.name().toLowerCase();
|
||||
String path = "/" + methodName;
|
||||
|
||||
return assertComposedAnnotationMapping(methodName, path, requestMethod);
|
||||
return assertComposedAnnotationMapping(mapping, methodName, path, requestMethod);
|
||||
}
|
||||
|
||||
private RequestMappingInfo assertComposedAnnotationMapping(String methodName, String path,
|
||||
RequestMethod requestMethod) throws Exception {
|
||||
private RequestMappingInfo assertComposedAnnotationMapping(
|
||||
RequestMappingHandlerMapping mapping, String methodName, String path, RequestMethod requestMethod) {
|
||||
|
||||
Class<?> clazz = ComposedAnnotationController.class;
|
||||
Method method = ClassUtils.getMethod(clazz, methodName, (Class<?>[]) null);
|
||||
RequestMappingInfo info = this.handlerMapping.getMappingForMethod(method, clazz);
|
||||
RequestMappingInfo info = mapping.getMappingForMethod(method, clazz);
|
||||
|
||||
assertThat(info).isNotNull();
|
||||
|
||||
Set<String> paths = info.getPatternsCondition().getPatterns();
|
||||
Set<String> paths = info.getPatternValues();
|
||||
assertThat(paths.size()).isEqualTo(1);
|
||||
assertThat(paths.iterator().next()).isEqualTo(path);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,19 +19,17 @@ package org.springframework.web.servlet.mvc.method.annotation;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@@ -45,6 +43,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
|
||||
import org.springframework.web.servlet.view.AbstractView;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
@@ -57,9 +56,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class UriTemplateServletAnnotationControllerHandlerMethodTests extends AbstractServletHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
public void simple() throws Exception {
|
||||
initServletWithControllers(SimpleUriTemplateController.class);
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<Boolean> pathPatternsArguments() {
|
||||
return Stream.of(true, false);
|
||||
}
|
||||
|
||||
|
||||
@PathPatternsParameterizedTest
|
||||
void simple(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(SimpleUriTemplateController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -67,9 +72,9 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-42-7");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiple() throws Exception {
|
||||
initServletWithControllers(MultipleUriTemplateController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void multiple(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(MultipleUriTemplateController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42;q=24/bookings/21-other;q=12");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -78,29 +83,29 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-42-q24-21-other-q12");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathVarsInModel() throws Exception {
|
||||
@PathPatternsParameterizedTest
|
||||
void pathVarsInModel(boolean usePathPatterns) throws Exception {
|
||||
final Map<String, Object> pathVars = new HashMap<>();
|
||||
pathVars.put("hotel", "42");
|
||||
pathVars.put("booking", 21);
|
||||
pathVars.put("other", "other");
|
||||
|
||||
WebApplicationContext wac = initServlet(context -> {
|
||||
WebApplicationContext wac = initDispatcherServlet(ViewRenderingController.class, usePathPatterns, context -> {
|
||||
RootBeanDefinition beanDef = new RootBeanDefinition(ModelValidatingViewResolver.class);
|
||||
beanDef.getConstructorArgumentValues().addGenericArgumentValue(pathVars);
|
||||
context.registerBeanDefinition("viewResolver", beanDef);
|
||||
}, ViewRenderingController.class);
|
||||
});
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42;q=1,2/bookings/21-other;q=3;r=R");
|
||||
HttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42;q=1,2/bookings/21-other;q=3;r=R");
|
||||
getServlet().service(request, new MockHttpServletResponse());
|
||||
|
||||
ModelValidatingViewResolver resolver = wac.getBean(ModelValidatingViewResolver.class);
|
||||
assertThat(resolver.validatedAttrCount).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void binding() throws Exception {
|
||||
initServletWithControllers(BindingUriTemplateController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void binding(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(BindingUriTemplateController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-11-18");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -112,16 +117,16 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getStatus()).isEqualTo(400);
|
||||
|
||||
initServletWithControllers(NonBindingUriTemplateController.class);
|
||||
initDispatcherServlet(NonBindingUriTemplateController.class, usePathPatterns);
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-foo-bar");
|
||||
response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getStatus()).isEqualTo(500);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ambiguous() throws Exception {
|
||||
initServletWithControllers(AmbiguousUriTemplateController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void ambiguous(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(AmbiguousUriTemplateController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/new");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -129,9 +134,9 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("specific");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relative() throws Exception {
|
||||
initServletWithControllers(RelativePathUriTemplateController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void relative(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(RelativePathUriTemplateController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -139,24 +144,27 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-42-21");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extension() throws Exception {
|
||||
initServlet(wac -> {
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
mappingDef.getPropertyValues().add("removeSemicolonContent", "false");
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}, SimpleUriTemplateController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void extension(boolean usePathPatterns) throws Exception {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42;jsessionid=c0o7fszeb1;q=24.xml");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-42-24");
|
||||
assertThat(response.getContentAsString())
|
||||
.isEqualTo(!usePathPatterns ? "test-42-24" : "test-42-24.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeConversionError() throws Exception {
|
||||
initServletWithControllers(SimpleUriTemplateController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void typeConversionError(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(SimpleUriTemplateController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.xml");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -164,9 +172,9 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getStatus()).as("Invalid response status code").isEqualTo(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void explicitSubPath() throws Exception {
|
||||
initServletWithControllers(ExplicitSubPathController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void explicitSubPath(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(ExplicitSubPathController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -174,9 +182,9 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-42");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicitSubPath() throws Exception {
|
||||
initServletWithControllers(ImplicitSubPathController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void implicitSubPath(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(ImplicitSubPathController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -184,9 +192,9 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-42");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void crud() throws Exception {
|
||||
initServletWithControllers(CrudController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void crud(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(CrudController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -224,9 +232,9 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("remove-42");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodNotSupported() throws Exception {
|
||||
initServletWithControllers(MethodNotAllowedController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void methodNotSupported(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(MethodNotAllowedController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/1");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -249,9 +257,9 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getStatus()).isEqualTo(405);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiPaths() throws Exception {
|
||||
initServletWithControllers(MultiPathController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void multiPaths(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(MultiPathController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/category/page/5");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -259,20 +267,21 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("handle4-page-5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customRegex() throws Exception {
|
||||
initServletWithControllers(CustomRegexController.class);
|
||||
@PathPatternsParameterizedTest
|
||||
void customRegex(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(CustomRegexController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42;q=1;q=2");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
assertThat(response.getContentAsString()).isEqualTo("test-42-;q=1;q=2-[1, 2]");
|
||||
assertThat(response.getContentAsString())
|
||||
.isEqualTo(!usePathPatterns ? "test-42-;q=1;q=2-[1, 2]" : "test-42--[1, 2]");
|
||||
}
|
||||
|
||||
@Test // gh-11306
|
||||
public void menuTree() throws Exception {
|
||||
initServletWithControllers(MenuTreeController.class);
|
||||
@PathPatternsParameterizedTest // gh-11306
|
||||
void menuTree(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(MenuTreeController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/book/menu/type/M5");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -280,9 +289,9 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("M5");
|
||||
}
|
||||
|
||||
@Test // gh-11542
|
||||
public void variableNames() throws Exception {
|
||||
initServletWithControllers(VariableNamesController.class);
|
||||
@PathPatternsParameterizedTest // gh-11542
|
||||
void variableNames(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(VariableNamesController.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -295,23 +304,25 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
assertThat(response.getContentAsString()).isEqualTo("bar-bar");
|
||||
}
|
||||
|
||||
@Test // gh-13187
|
||||
public void variableNamesWithUrlExtension() throws Exception {
|
||||
initServlet(wac -> {
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
}, VariableNamesController.class);
|
||||
@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);
|
||||
}
|
||||
});
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo.json");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertThat(response.getContentAsString()).isEqualTo("foo-foo");
|
||||
assertThat(response.getContentAsString()).isEqualTo(!usePathPatterns ? "foo-foo" : "foo-foo.json");
|
||||
}
|
||||
|
||||
@Test // gh-11643
|
||||
public void doIt() throws Exception {
|
||||
initServletWithControllers(Spr6978Controller.class);
|
||||
@PathPatternsParameterizedTest // gh-11643
|
||||
void doIt(boolean usePathPatterns) throws Exception {
|
||||
initDispatcherServlet(Spr6978Controller.class, usePathPatterns);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/100");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -344,7 +355,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class SimpleUriTemplateController {
|
||||
|
||||
@RequestMapping("/{root}")
|
||||
public void handle(@PathVariable("root") int root, @MatrixVariable(required=false, defaultValue="7") int q,
|
||||
void handle(@PathVariable("root") int root, @MatrixVariable(required=false, defaultValue="7") String q,
|
||||
Writer writer) throws IOException {
|
||||
|
||||
assertThat(root).as("Invalid path variable value").isEqualTo(42);
|
||||
@@ -357,7 +368,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class MultipleUriTemplateController {
|
||||
|
||||
@RequestMapping("/hotels/{hotel}/bookings/{booking}-{other}")
|
||||
public void handle(@PathVariable("hotel") String hotel,
|
||||
void handle(@PathVariable("hotel") String hotel,
|
||||
@PathVariable int booking,
|
||||
@PathVariable String other,
|
||||
@MatrixVariable(name = "q", pathVar = "hotel") int qHotel,
|
||||
@@ -374,12 +385,12 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class ViewRenderingController {
|
||||
|
||||
@RequestMapping("/hotels/{hotel}/bookings/{booking}-{other}")
|
||||
public void handle(@PathVariable("hotel") String hotel, @PathVariable int booking,
|
||||
void handle(@PathVariable("hotel") String hotel, @PathVariable int booking,
|
||||
@PathVariable String other, @MatrixVariable MultiValueMap<String, String> params) {
|
||||
|
||||
assertThat(hotel).as("Invalid path variable value").isEqualTo("42");
|
||||
assertThat(booking).as("Invalid path variable value").isEqualTo(21);
|
||||
assertThat(params.get("q")).isEqualTo(Arrays.asList("1", "2", "3"));
|
||||
assertThat(params.get("q")).containsExactlyInAnyOrder("1", "2", "3");
|
||||
assertThat(params.getFirst("r")).isEqualTo("R");
|
||||
}
|
||||
|
||||
@@ -389,7 +400,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class BindingUriTemplateController {
|
||||
|
||||
@InitBinder
|
||||
public void initBinder(WebDataBinder binder, @PathVariable("hotel") String hotel) {
|
||||
void initBinder(WebDataBinder binder, @PathVariable("hotel") String hotel) {
|
||||
assertThat(hotel).as("Invalid path variable value").isEqualTo("42");
|
||||
binder.initBeanPropertyAccess();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
@@ -398,7 +409,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
}
|
||||
|
||||
@RequestMapping("/hotels/{hotel}/dates/{date}")
|
||||
public void handle(@PathVariable("hotel") String hotel, @PathVariable Date date, Writer writer)
|
||||
void handle(@PathVariable("hotel") String hotel, @PathVariable Date date, Writer writer)
|
||||
throws IOException {
|
||||
assertThat(hotel).as("Invalid path variable value").isEqualTo("42");
|
||||
assertThat(date).as("Invalid path variable value").isEqualTo(new GregorianCalendar(2008, 10, 18).getTime());
|
||||
@@ -410,7 +421,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class NonBindingUriTemplateController {
|
||||
|
||||
@RequestMapping("/hotels/{hotel}/dates/{date}")
|
||||
public void handle(@PathVariable("hotel") String hotel, @PathVariable Date date, Writer writer)
|
||||
void handle(@PathVariable("hotel") String hotel, @PathVariable Date date, Writer writer)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
@@ -421,7 +432,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class RelativePathUriTemplateController {
|
||||
|
||||
@RequestMapping("bookings/{booking}")
|
||||
public void handle(@PathVariable("hotel") String hotel, @PathVariable int booking, Writer writer)
|
||||
void handle(@PathVariable("hotel") String hotel, @PathVariable int booking, Writer writer)
|
||||
throws IOException {
|
||||
assertThat(hotel).as("Invalid path variable value").isEqualTo("42");
|
||||
assertThat(booking).as("Invalid path variable value").isEqualTo(21);
|
||||
@@ -435,18 +446,18 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class AmbiguousUriTemplateController {
|
||||
|
||||
@RequestMapping("/{hotel}")
|
||||
public void handleVars(@PathVariable("hotel") String hotel, Writer writer) throws IOException {
|
||||
void handleVars(@PathVariable("hotel") String hotel, Writer writer) throws IOException {
|
||||
assertThat(hotel).as("Invalid path variable value").isEqualTo("42");
|
||||
writer.write("variables");
|
||||
}
|
||||
|
||||
@RequestMapping("/new")
|
||||
public void handleSpecific(Writer writer) throws IOException {
|
||||
void handleSpecific(Writer writer) throws IOException {
|
||||
writer.write("specific");
|
||||
}
|
||||
|
||||
@RequestMapping("/*")
|
||||
public void handleWildCard(Writer writer) throws IOException {
|
||||
void handleWildCard(Writer writer) throws IOException {
|
||||
writer.write("wildcard");
|
||||
}
|
||||
|
||||
@@ -457,7 +468,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class ExplicitSubPathController {
|
||||
|
||||
@RequestMapping("{hotel}")
|
||||
public void handleHotel(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
void handleHotel(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("test-" + hotel);
|
||||
}
|
||||
|
||||
@@ -468,7 +479,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class ImplicitSubPathController {
|
||||
|
||||
@RequestMapping("{hotel}")
|
||||
public void handleHotel(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
void handleHotel(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("test-" + hotel);
|
||||
}
|
||||
}
|
||||
@@ -477,7 +488,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class CustomRegexController {
|
||||
|
||||
@RequestMapping("/{root:\\d+}{params}")
|
||||
public void handle(@PathVariable("root") int root, @PathVariable("params") String paramString,
|
||||
void handle(@PathVariable("root") int root, @PathVariable("params") String paramString,
|
||||
@MatrixVariable List<Integer> q, Writer writer) throws IOException {
|
||||
|
||||
assertThat(root).as("Invalid path variable value").isEqualTo(42);
|
||||
@@ -489,7 +500,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class DoubleController {
|
||||
|
||||
@RequestMapping("/lat/{latitude}/long/{longitude}")
|
||||
public void testLatLong(@PathVariable Double latitude, @PathVariable Double longitude, Writer writer)
|
||||
void testLatLong(@PathVariable Double latitude, @PathVariable Double longitude, Writer writer)
|
||||
throws IOException {
|
||||
writer.write("latitude-" + latitude + "-longitude-" + longitude);
|
||||
}
|
||||
@@ -501,27 +512,27 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class CrudController {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public void list(Writer writer) throws IOException {
|
||||
void list(Writer writer) throws IOException {
|
||||
writer.write("list");
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public void create(Writer writer) throws IOException {
|
||||
void create(Writer writer) throws IOException {
|
||||
writer.write("create");
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{hotel}", method = RequestMethod.GET)
|
||||
public void show(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
void show(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("show-" + hotel);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "{hotel}", method = RequestMethod.PUT)
|
||||
public void createOrUpdate(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
void createOrUpdate(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("createOrUpdate-" + hotel);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "{hotel}", method = RequestMethod.DELETE)
|
||||
public void remove(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
void remove(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("remove-" + hotel);
|
||||
}
|
||||
|
||||
@@ -532,19 +543,19 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class MethodNotAllowedController {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public void list(Writer writer) {
|
||||
void list(Writer writer) {
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "{hotelId}")
|
||||
public void show(@PathVariable long hotelId, Writer writer) {
|
||||
void show(@PathVariable long hotelId, Writer writer) {
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.PUT, value = "{hotelId}")
|
||||
public void createOrUpdate(@PathVariable long hotelId, Writer writer) {
|
||||
void createOrUpdate(@PathVariable long hotelId, Writer writer) {
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{hotelId}")
|
||||
public void remove(@PathVariable long hotelId, Writer writer) {
|
||||
void remove(@PathVariable long hotelId, Writer writer) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,25 +564,25 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class MultiPathController {
|
||||
|
||||
@RequestMapping(value = {"/{category}/page/{page}", "/*/{category}/page/{page}"})
|
||||
public void category(@PathVariable String category, @PathVariable int page, Writer writer) throws IOException {
|
||||
void category(@PathVariable String category, @PathVariable int page, Writer writer) throws IOException {
|
||||
writer.write("handle1-");
|
||||
writer.write("category-" + category);
|
||||
writer.write("page-" + page);
|
||||
}
|
||||
|
||||
@RequestMapping(value = {"/{category}", "/*/{category}"})
|
||||
public void category(@PathVariable String category, Writer writer) throws IOException {
|
||||
void category(@PathVariable String category, Writer writer) throws IOException {
|
||||
writer.write("handle2-");
|
||||
writer.write("category-" + category);
|
||||
}
|
||||
|
||||
@RequestMapping(value = {""})
|
||||
public void category(Writer writer) throws IOException {
|
||||
void category(Writer writer) throws IOException {
|
||||
writer.write("handle3");
|
||||
}
|
||||
|
||||
@RequestMapping(value = {"/page/{page}"})
|
||||
public void category(@PathVariable int page, Writer writer) throws IOException {
|
||||
void category(@PathVariable int page, Writer writer) throws IOException {
|
||||
writer.write("handle4-");
|
||||
writer.write("page-" + page);
|
||||
}
|
||||
@@ -583,7 +594,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class MenuTreeController {
|
||||
|
||||
@RequestMapping("type/{var}")
|
||||
public void getFirstLevelFunctionNodes(@PathVariable("var") String var, Writer writer) throws IOException {
|
||||
void getFirstLevelFunctionNodes(@PathVariable("var") String var, Writer writer) throws IOException {
|
||||
writer.write(var);
|
||||
}
|
||||
}
|
||||
@@ -593,12 +604,12 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class VariableNamesController {
|
||||
|
||||
@RequestMapping(value = "/{foo}", method=RequestMethod.GET)
|
||||
public void foo(@PathVariable String foo, Writer writer) throws IOException {
|
||||
void foo(@PathVariable String foo, Writer writer) throws IOException {
|
||||
writer.write("foo-" + foo);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{bar}", method=RequestMethod.DELETE)
|
||||
public void bar(@PathVariable String bar, Writer writer) throws IOException {
|
||||
void bar(@PathVariable String bar, Writer writer) throws IOException {
|
||||
writer.write("bar-" + bar);
|
||||
}
|
||||
}
|
||||
@@ -607,18 +618,18 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
public static class Spr6978Controller {
|
||||
|
||||
@RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET)
|
||||
public void loadEntity(@PathVariable final String type, @PathVariable final long id, Writer writer)
|
||||
void loadEntity(@PathVariable final String type, @PathVariable final long id, Writer writer)
|
||||
throws IOException {
|
||||
writer.write("loadEntity:" + type + ":" + id);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/module/{id}", method = RequestMethod.GET)
|
||||
public void loadModule(@PathVariable final long id, Writer writer) throws IOException {
|
||||
void loadModule(@PathVariable final long id, Writer writer) throws IOException {
|
||||
writer.write("loadModule:" + id);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{type}/{id}", method = RequestMethod.POST)
|
||||
public void publish(@PathVariable final String type, @PathVariable final long id, Writer writer)
|
||||
void publish(@PathVariable final String type, @PathVariable final long id, Writer writer)
|
||||
throws IOException {
|
||||
writer.write("publish:" + type + ":" + id);
|
||||
}
|
||||
@@ -655,12 +666,12 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||
}
|
||||
|
||||
// @Disabled("ControllerClassNameHandlerMapping")
|
||||
// public void controllerClassName() throws Exception {
|
||||
// void controllerClassName() throws Exception {
|
||||
|
||||
// @Disabled("useDefaultSuffixPattern property not supported")
|
||||
// public void doubles() throws Exception {
|
||||
// void doubles() throws Exception {
|
||||
|
||||
// @Disabled("useDefaultSuffixPattern property not supported")
|
||||
// public void noDefaultSuffixPattern() throws Exception {
|
||||
// void noDefaultSuffixPattern() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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,9 +16,11 @@
|
||||
|
||||
package org.springframework.web.servlet.view;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
|
||||
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -31,110 +33,99 @@ public class DefaultRequestToViewNameTranslatorTests {
|
||||
|
||||
private static final String VIEW_NAME = "apple";
|
||||
private static final String EXTENSION = ".html";
|
||||
private static final String CONTEXT_PATH = "/sundays";
|
||||
|
||||
private DefaultRequestToViewNameTranslator translator;
|
||||
private MockHttpServletRequest request;
|
||||
private final DefaultRequestToViewNameTranslator translator = new DefaultRequestToViewNameTranslator();
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
this.translator = new DefaultRequestToViewNameTranslator();
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.request.setContextPath(CONTEXT_PATH);
|
||||
@SuppressWarnings("unused")
|
||||
private static Stream<Function<String, MockHttpServletRequest>> pathPatternsArguments() {
|
||||
return PathPatternsTestUtils.requestArguments("/sundays");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetViewNameLeavesLeadingSlashIfSoConfigured() {
|
||||
request.setRequestURI(CONTEXT_PATH + "/" + VIEW_NAME + "/");
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameLeavesLeadingSlashIfSoConfigured(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME + "/");
|
||||
this.translator.setStripLeadingSlash(false);
|
||||
assertViewName("/" + VIEW_NAME);
|
||||
assertViewName(request, "/" + VIEW_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameLeavesTrailingSlashIfSoConfigured() {
|
||||
request.setRequestURI(CONTEXT_PATH + "/" + VIEW_NAME + "/");
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameLeavesTrailingSlashIfSoConfigured(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME + "/");
|
||||
this.translator.setStripTrailingSlash(false);
|
||||
assertViewName(VIEW_NAME + "/");
|
||||
assertViewName(request, VIEW_NAME + "/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameLeavesExtensionIfSoConfigured() {
|
||||
request.setRequestURI(CONTEXT_PATH + "/" + VIEW_NAME + EXTENSION);
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameLeavesExtensionIfSoConfigured(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME + EXTENSION);
|
||||
this.translator.setStripExtension(false);
|
||||
assertViewName(VIEW_NAME + EXTENSION);
|
||||
assertViewName(request, VIEW_NAME + EXTENSION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameWithDefaultConfiguration() {
|
||||
request.setRequestURI(CONTEXT_PATH + VIEW_NAME + EXTENSION);
|
||||
assertViewName(VIEW_NAME);
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameWithDefaultConfiguration(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME + EXTENSION);
|
||||
assertViewName(request, VIEW_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameWithCustomSeparator() {
|
||||
request.setRequestURI(CONTEXT_PATH + VIEW_NAME + "/fiona" + EXTENSION);
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameWithCustomSeparator(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME + "/fiona" + EXTENSION);
|
||||
this.translator.setSeparator("_");
|
||||
assertViewName(VIEW_NAME + "_fiona");
|
||||
assertViewName(request, VIEW_NAME + "_fiona");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameWithNoExtension() {
|
||||
request.setRequestURI(CONTEXT_PATH + VIEW_NAME);
|
||||
assertViewName(VIEW_NAME);
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameWithNoExtension(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME);
|
||||
assertViewName(request, VIEW_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameWithSemicolonContent() {
|
||||
request.setRequestURI(CONTEXT_PATH + VIEW_NAME + ";a=A;b=B");
|
||||
assertViewName(VIEW_NAME);
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameWithSemicolonContent(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME + ";a=A;b=B");
|
||||
assertViewName(request, VIEW_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameWithPrefix() {
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameWithPrefix(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
final String prefix = "fiona_";
|
||||
request.setRequestURI(CONTEXT_PATH + VIEW_NAME);
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME);
|
||||
this.translator.setPrefix(prefix);
|
||||
assertViewName(prefix + VIEW_NAME);
|
||||
assertViewName(request, prefix + VIEW_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameWithNullPrefix() {
|
||||
request.setRequestURI(CONTEXT_PATH + VIEW_NAME);
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameWithNullPrefix(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME);
|
||||
this.translator.setPrefix(null);
|
||||
assertViewName(VIEW_NAME);
|
||||
assertViewName(request, VIEW_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameWithSuffix() {
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameWithSuffix(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
final String suffix = ".fiona";
|
||||
request.setRequestURI(CONTEXT_PATH + VIEW_NAME);
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME);
|
||||
this.translator.setSuffix(suffix);
|
||||
assertViewName(VIEW_NAME + suffix);
|
||||
assertViewName(request, VIEW_NAME + suffix);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViewNameWithNullSuffix() {
|
||||
request.setRequestURI(CONTEXT_PATH + VIEW_NAME);
|
||||
@PathPatternsParameterizedTest
|
||||
void testGetViewNameWithNullSuffix(Function<String, MockHttpServletRequest> requestFactory) {
|
||||
MockHttpServletRequest request = requestFactory.apply(VIEW_NAME);
|
||||
this.translator.setSuffix(null);
|
||||
assertViewName(VIEW_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrySetUrlPathHelperToNull() {
|
||||
try {
|
||||
this.translator.setUrlPathHelper(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
assertViewName(request, VIEW_NAME);
|
||||
}
|
||||
|
||||
|
||||
private void assertViewName(String expectedViewName) {
|
||||
String actualViewName = this.translator.getViewName(this.request);
|
||||
private void assertViewName(MockHttpServletRequest request, String expectedViewName) {
|
||||
String actualViewName = this.translator.getViewName(request);
|
||||
assertThat(actualViewName).isNotNull();
|
||||
assertThat(actualViewName).as("Did not get the expected viewName from the DefaultRequestToViewNameTranslator.getViewName(..)").isEqualTo(expectedViewName);
|
||||
assertThat(actualViewName)
|
||||
.as("Did not get the expected viewName from the DefaultRequestToViewNameTranslator.getViewName(..)")
|
||||
.isEqualTo(expectedViewName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user