spring CrossOriginTests 源码

  • 2022-08-08
  • 浏览 (307)

spring CrossOriginTests 代码

文件路径:/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/CrossOriginTests.java

/*
 * Copyright 2002-2022 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.method.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Properties;
import java.util.stream.Stream;

import jakarta.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.BeforeEach;

import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.annotation.AliasFor;
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;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerInterceptor;
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 static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;

/**
 * Tests for {@link CrossOrigin @CrossOrigin} annotated methods.
 *
 * @author Sebastien Deleuze
 * @author Sam Brannen
 * @author Nicolas Labrot
 * @author Rossen Stoyanchev
 */
class CrossOriginTests {

	@SuppressWarnings("unused")
	static Stream<TestRequestMappingInfoHandlerMapping> pathPatternsArguments() {
		StaticWebApplicationContext wac = new StaticWebApplicationContext();
		Properties props = new Properties();
		props.setProperty("myOrigin", "https://example.com");
		props.setProperty("myDomainPattern", "http://*.example.com");
		wac.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("ps", props));
		wac.registerSingleton("ppc", PropertySourcesPlaceholderConfigurer.class);
		wac.refresh();

		TestRequestMappingInfoHandlerMapping mapping1 = new TestRequestMappingInfoHandlerMapping();
		wac.getAutowireCapableBeanFactory().initializeBean(mapping1, "mapping1");

		TestRequestMappingInfoHandlerMapping mapping2 = new TestRequestMappingInfoHandlerMapping();
		mapping2.setPatternParser(null);
		wac.getAutowireCapableBeanFactory().initializeBean(mapping2, "mapping2");
		wac.close();

		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/");
	}


	@PathPatternsParameterizedTest
	void noAnnotationWithoutOrigin(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		MockHttpServletRequest request = new MockHttpServletRequest("GET", "/no");
		HandlerExecutionChain chain = mapping.getHandler(request);
		assertThat(getCorsConfiguration(chain, false)).isNull();
	}

	@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 = mapping.getHandler(request);
		assertThat(chain).isNotNull();
		assertThat(chain.getHandler().toString())
				.endsWith("RequestMappingInfoHandlerMapping$HttpOptionsHandler#handle()");
	}

	@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 = mapping.getHandler(request);
		assertThat(chain).isNotNull();
		assertThat(chain.getHandler().getClass().getName()).endsWith("AbstractHandlerMapping$PreFlightHandler");
	}

	@PathPatternsParameterizedTest  // SPR-12931
	void noAnnotationWithOrigin(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		this.request.setRequestURI("/no");
		HandlerExecutionChain chain = mapping.getHandler(request);
		assertThat(getCorsConfiguration(chain, false)).isNull();
	}

	@PathPatternsParameterizedTest  // SPR-12931
	void noAnnotationPostWithOrigin(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		this.request.setMethod("POST");
		this.request.setRequestURI("/no");
		HandlerExecutionChain chain = mapping.getHandler(request);
		assertThat(getCorsConfiguration(chain, false)).isNull();
	}

	@PathPatternsParameterizedTest
	void defaultAnnotation(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		this.request.setRequestURI("/default");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).containsExactly("*");
		assertThat(config.getAllowCredentials()).isNull();
		assertThat(config.getAllowedHeaders()).containsExactly("*");
		assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue();
		assertThat(config.getMaxAge()).isEqualTo(Long.valueOf(1800));
	}

	@PathPatternsParameterizedTest
	void customized(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		this.request.setRequestURI("/customized");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		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(Long.valueOf(123));
		assertThat(config.getAllowCredentials()).isFalse();
	}

	@PathPatternsParameterizedTest
	void customOriginDefinedViaValueAttribute(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		this.request.setRequestURI("/customOrigin");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedOrigins()).isEqualTo(Collections.singletonList("https://example.com"));
		assertThat(config.getAllowCredentials()).isNull();
	}

	@PathPatternsParameterizedTest
	void customOriginDefinedViaPlaceholder(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		this.request.setRequestURI("/someOrigin");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedOrigins()).isEqualTo(Collections.singletonList("https://example.com"));
		assertThat(config.getAllowCredentials()).isNull();
	}

	@PathPatternsParameterizedTest
	public void customOriginPatternViaValueAttribute(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		this.request.setRequestURI("/customOriginPattern");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedOrigins()).isNull();
		assertThat(config.getAllowedOriginPatterns()).isEqualTo(Collections.singletonList("http://*.example.com"));
		assertThat(config.getAllowCredentials()).isNull();
	}

	@PathPatternsParameterizedTest
	public void customOriginPatternViaPlaceholder(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelController());
		this.request.setRequestURI("/customOriginPatternPlaceholder");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedOrigins()).isNull();
		assertThat(config.getAllowedOriginPatterns()).isEqualTo(Collections.singletonList("http://*.example.com"));
		assertThat(config.getAllowCredentials()).isNull();
	}

	@PathPatternsParameterizedTest
	void bogusAllowCredentialsValue(TestRequestMappingInfoHandlerMapping mapping) {
		assertThatIllegalStateException()
				.isThrownBy(() -> mapping.registerHandler(new MethodLevelControllerWithBogusAllowCredentialsValue()))
				.withMessageContaining("@CrossOrigin's allowCredentials")
				.withMessageContaining("current value is [bogus]");
	}

	@PathPatternsParameterizedTest
	void allowCredentialsWithDefaultOrigin(TestRequestMappingInfoHandlerMapping mapping) {
		assertThatIllegalArgumentException()
				.isThrownBy(() -> mapping.registerHandler(new CredentialsWithDefaultOriginController()))
				.withMessageContaining("When allowCredentials is true, allowedOrigins cannot contain");
	}

	@PathPatternsParameterizedTest
	void allowCredentialsWithWildcardOrigin(TestRequestMappingInfoHandlerMapping mapping) {
		assertThatIllegalArgumentException()
				.isThrownBy(() -> mapping.registerHandler(new CredentialsWithWildcardOriginController()))
				.withMessageContaining("When allowCredentials is true, allowedOrigins cannot contain");
	}

	@PathPatternsParameterizedTest
	void classLevel(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new ClassLevelController());

		this.request.setRequestURI("/foo");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).containsExactly("*");
		assertThat(config.getAllowCredentials()).isFalse();

		this.request.setRequestURI("/bar");
		chain = mapping.getHandler(request);
		config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).containsExactly("*");
		assertThat(config.getAllowCredentials()).isFalse();

		this.request.setRequestURI("/baz");
		chain = mapping.getHandler(request);
		config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).isNull();
		assertThat(config.getAllowedOriginPatterns()).containsExactly("*");
		assertThat(config.getAllowCredentials()).isTrue();
	}

	@PathPatternsParameterizedTest // SPR-13468
	void classLevelComposedAnnotation(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new ClassLevelMappingWithComposedAnnotation());

		this.request.setRequestURI("/foo");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).containsExactly("http://www.foo.example");
		assertThat(config.getAllowCredentials()).isTrue();
	}

	@PathPatternsParameterizedTest // SPR-13468
	void methodLevelComposedAnnotation(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MethodLevelMappingWithComposedAnnotation());

		this.request.setRequestURI("/foo");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).containsExactly("http://www.foo.example");
		assertThat(config.getAllowCredentials()).isTrue();
	}

	@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 = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, true);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).containsExactly("*");
		assertThat(config.getAllowCredentials()).isNull();
		assertThat(config.getAllowedHeaders()).containsExactly("*");
		assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue();
		assertThat(config.getMaxAge()).isEqualTo(Long.valueOf(1800));
	}

	@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 = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, true);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("*");
		assertThat(config.getAllowedOrigins()).isNull();
		assertThat(config.getAllowedOriginPatterns()).containsExactly("*");
		assertThat(config.getAllowedHeaders()).containsExactly("*");
		assertThat(config.getAllowCredentials()).isTrue();
		assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue();
		assertThat(config.getMaxAge()).isNull();
	}

	@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 = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, true);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("*");
		assertThat(config.getAllowedOrigins()).isNull();
		assertThat(config.getAllowedOriginPatterns()).containsExactly("*");
		assertThat(config.getAllowedHeaders()).containsExactly("*");
		assertThat(config.getAllowCredentials()).isTrue();
		assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue();
		assertThat(config.getMaxAge()).isNull();
	}

	@PathPatternsParameterizedTest
	void preFlightRequestWithoutRequestMethodHeader(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/default");
		request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
		assertThat(mapping.getHandler(request)).isNull();
	}

	@PathPatternsParameterizedTest
	void maxAgeWithDefaultOrigin(TestRequestMappingInfoHandlerMapping mapping) throws Exception {
		mapping.registerHandler(new MaxAgeWithDefaultOriginController());

		this.request.setRequestURI("/classAge");
		HandlerExecutionChain chain = mapping.getHandler(request);
		CorsConfiguration config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).containsExactly("*");
		assertThat(config.getMaxAge()).isEqualTo(10);

		this.request.setRequestURI("/methodAge");
		chain = mapping.getHandler(request);
		config = getCorsConfiguration(chain, false);
		assertThat(config).isNotNull();
		assertThat(config.getAllowedMethods()).containsExactly("GET");
		assertThat(config.getAllowedOrigins()).containsExactly("*");
		assertThat(config.getMaxAge()).isEqualTo(100);
	}


	@Nullable
	private CorsConfiguration getCorsConfiguration(@Nullable HandlerExecutionChain chain, boolean isPreFlightRequest) {
		assertThat(chain).isNotNull();
		if (isPreFlightRequest) {
			Object handler = chain.getHandler();
			assertThat(handler.getClass().getSimpleName()).isEqualTo("PreFlightHandler");
			DirectFieldAccessor accessor = new DirectFieldAccessor(handler);
			return (CorsConfiguration)accessor.getPropertyValue("config");
		}
		else {
			for (HandlerInterceptor interceptor : chain.getInterceptorList()) {
				if (interceptor.getClass().getSimpleName().equals("CorsInterceptor")) {
					DirectFieldAccessor accessor = new DirectFieldAccessor(interceptor);
					return (CorsConfiguration) accessor.getPropertyValue("config");
				}
			}
		}
		return null;
	}


	@Controller
	@SuppressWarnings("unused")
	private static class MethodLevelController {

		@GetMapping("/no")
		public void noAnnotation() {
		}

		@PostMapping("/no")
		public void noAnnotationPost() {
		}

		@CrossOrigin
		@GetMapping(path = "/default")
		public void defaultAnnotation() {
		}

		@CrossOrigin
		@GetMapping(path = "/default", params = "q")
		public void defaultAnnotationWithParams() {
		}

		@CrossOrigin
		@GetMapping(path = "/ambiguous-header", headers = "header1=a")
		public void ambiguousHeader1a() {
		}

		@CrossOrigin
		@GetMapping(path = "/ambiguous-header", headers = "header1=b")
		public void ambiguousHeader1b() {
		}

		@CrossOrigin
		@GetMapping(path = "/ambiguous-produces", produces = "application/xml")
		public String ambiguousProducesXml() {
			return "<a></a>";
		}

		@CrossOrigin
		@GetMapping(path = "/ambiguous-produces", produces = "application/json")
		public String ambiguousProducesJson() {
			return "{}";
		}

		@CrossOrigin(origins = { "https://site1.com", "https://site2.com" },
				allowedHeaders = { "header1", "header2" },
				exposedHeaders = { "header3", "header4" },
				methods = RequestMethod.DELETE,
				maxAge = 123,
				allowCredentials = "false")
		@RequestMapping(path = "/customized", method = { RequestMethod.GET, RequestMethod.POST })
		public void customized() {
		}

		@CrossOrigin("https://example.com")
		@RequestMapping("/customOrigin")
		public void customOriginDefinedViaValueAttribute() {
		}

		@CrossOrigin("${myOrigin}")
		@RequestMapping("/someOrigin")
		public void customOriginDefinedViaPlaceholder() {
		}

		@CrossOrigin(originPatterns = "http://*.example.com")
		@RequestMapping("/customOriginPattern")
		public void customOriginPatternDefinedViaValueAttribute() {
		}

		@CrossOrigin(originPatterns = "${myDomainPattern}")
		@RequestMapping("/customOriginPatternPlaceholder")
		public void customOriginPatternDefinedViaPlaceholder() {
		}
	}


	@Controller
	@SuppressWarnings("unused")
	private static class MethodLevelControllerWithBogusAllowCredentialsValue {

		@CrossOrigin(allowCredentials = "bogus")
		@RequestMapping("/bogus")
		public void bogusAllowCredentialsValue() {
		}
	}


	@Controller
	@CrossOrigin(allowCredentials = "false")
	private static class ClassLevelController {

		@RequestMapping(path = "/foo", method = RequestMethod.GET)
		public void foo() {
		}

		@CrossOrigin
		@RequestMapping(path = "/bar", method = RequestMethod.GET)
		public void bar() {
		}

		@CrossOrigin(originPatterns = "*", allowCredentials = "true")
		@RequestMapping(path = "/baz", method = RequestMethod.GET)
		public void baz() {
		}
	}

	@Controller
	@CrossOrigin(maxAge = 10)
	private static class MaxAgeWithDefaultOriginController {

		@CrossOrigin
		@GetMapping("/classAge")
		void classAge() {
		}

		@CrossOrigin(maxAge = 100)
		@GetMapping("/methodAge")
		void methodAge() {
		}
	}

	@Controller
	@CrossOrigin(allowCredentials = "true")
	private static class CredentialsWithDefaultOriginController {

		@GetMapping(path = "/no-origin")
		public void noOrigin() {
		}
	}


	@Controller
	@CrossOrigin(allowCredentials = "true")
	private static class CredentialsWithWildcardOriginController {

		@GetMapping(path = "/no-origin")
		@CrossOrigin(origins = "*")
		public void wildcardOrigin() {
		}
	}


	@Target({ElementType.METHOD, ElementType.TYPE})
	@Retention(RetentionPolicy.RUNTIME)
	@CrossOrigin
	private @interface ComposedCrossOrigin {

		@AliasFor(annotation = CrossOrigin.class)
		String[] origins() default {};

		@AliasFor(annotation = CrossOrigin.class)
		String allowCredentials() default "";
	}


	@Controller
	@ComposedCrossOrigin(origins = "http://www.foo.example/", allowCredentials = "true")
	private static class ClassLevelMappingWithComposedAnnotation {

		@RequestMapping(path = "/foo", method = RequestMethod.GET)
		public void foo() {
		}
	}


	@Controller
	private static class MethodLevelMappingWithComposedAnnotation {

		@RequestMapping(path = "/foo", method = RequestMethod.GET)
		@ComposedCrossOrigin(origins = "http://www.foo.example/", allowCredentials = "true")
		public void foo() {
		}
	}


	private static class TestRequestMappingInfoHandlerMapping extends RequestMappingHandlerMapping {

		void registerHandler(Object handler) {
			super.detectHandlerMethods(handler);
		}

		@Override
		protected boolean isHandler(Class<?> beanType) {
			return AnnotationUtils.findAnnotation(beanType, Controller.class) != null;
		}

		@Override
		protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
			RequestMapping annotation = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
			if (annotation != 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);
		}

		@Override
		public String toString() {
			return "PatternParser = " + (getPatternParser() != null ? getPatternParser().getClass().getSimpleName() : null) ;
		}
	}

}

相关信息

spring 源码目录

相关文章

spring AbstractRequestAttributesArgumentResolverTests 源码

spring AbstractServletHandlerMethodTests 源码

spring DeferredResultReturnValueHandlerTests 源码

spring ExceptionHandlerExceptionResolverTests 源码

spring ExtendedServletRequestDataBinderTests 源码

spring HandlerMethodAnnotationDetectionTests 源码

spring HttpEntityMethodProcessorMockTests 源码

spring HttpEntityMethodProcessorTests 源码

spring MatrixVariablesMapMethodArgumentResolverTests 源码

spring MatrixVariablesMethodArgumentResolverTests 源码

0  赞