Support @CrossOrigin as a merged composed annotation
Issue: SPR-13468
This commit is contained in:
parent
74b05118eb
commit
e4c0859d41
|
@ -286,8 +286,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||||
@Override
|
@Override
|
||||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
|
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
|
||||||
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
|
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
|
||||||
CrossOrigin typeAnnotation = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), CrossOrigin.class);
|
CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), CrossOrigin.class);
|
||||||
CrossOrigin methodAnnotation = AnnotationUtils.findAnnotation(method, CrossOrigin.class);
|
CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);
|
||||||
|
|
||||||
if (typeAnnotation == null && methodAnnotation == null) {
|
if (typeAnnotation == null && methodAnnotation == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
package org.springframework.web.servlet.mvc.method.annotation;
|
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.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@ -25,6 +29,7 @@ import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import org.springframework.beans.DirectFieldAccessor;
|
import org.springframework.beans.DirectFieldAccessor;
|
||||||
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||||
|
@ -53,6 +58,7 @@ import static org.junit.Assert.*;
|
||||||
*
|
*
|
||||||
* @author Sebastien Deleuze
|
* @author Sebastien Deleuze
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
|
* @author Nicolas Labrot
|
||||||
*/
|
*/
|
||||||
public class CrossOriginTests {
|
public class CrossOriginTests {
|
||||||
|
|
||||||
|
@ -79,8 +85,7 @@ public class CrossOriginTests {
|
||||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/no");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/no");
|
||||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
assertNull(getCorsConfiguration(chain, false));
|
||||||
assertNull(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // SPR-12931
|
@Test // SPR-12931
|
||||||
|
@ -88,8 +93,7 @@ public class CrossOriginTests {
|
||||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||||
this.request.setRequestURI("/no");
|
this.request.setRequestURI("/no");
|
||||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
assertNull(getCorsConfiguration(chain, false));
|
||||||
assertNull(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // SPR-12931
|
@Test // SPR-12931
|
||||||
|
@ -98,8 +102,7 @@ public class CrossOriginTests {
|
||||||
this.request.setMethod("POST");
|
this.request.setMethod("POST");
|
||||||
this.request.setRequestURI("/no");
|
this.request.setRequestURI("/no");
|
||||||
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
assertNull(getCorsConfiguration(chain, false));
|
||||||
assertNull(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -180,6 +183,32 @@ public class CrossOriginTests {
|
||||||
assertTrue(config.getAllowCredentials());
|
assertTrue(config.getAllowCredentials());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // SPR-13468
|
||||||
|
public void classLevelComposedAnnotation() throws Exception {
|
||||||
|
this.handlerMapping.registerHandler(new ClassLevelMappingWithComposedAnnotation());
|
||||||
|
|
||||||
|
this.request.setRequestURI("/foo");
|
||||||
|
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||||
|
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||||
|
assertNotNull(config);
|
||||||
|
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
|
||||||
|
assertArrayEquals(new String[]{"http://foo.com"}, config.getAllowedOrigins().toArray());
|
||||||
|
assertTrue(config.getAllowCredentials());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // SPR-13468
|
||||||
|
public void methodLevelComposedAnnotation() throws Exception {
|
||||||
|
this.handlerMapping.registerHandler(new MethodLevelMappingWithComposedAnnotation());
|
||||||
|
|
||||||
|
this.request.setRequestURI("/foo");
|
||||||
|
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
|
||||||
|
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||||
|
assertNotNull(config);
|
||||||
|
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
|
||||||
|
assertArrayEquals(new String[]{"http://foo.com"}, config.getAllowedOrigins().toArray());
|
||||||
|
assertTrue(config.getAllowCredentials());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void preFlightRequest() throws Exception {
|
public void preFlightRequest() throws Exception {
|
||||||
this.handlerMapping.registerHandler(new MethodLevelController());
|
this.handlerMapping.registerHandler(new MethodLevelController());
|
||||||
|
@ -345,6 +374,33 @@ public class CrossOriginTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@CrossOrigin
|
||||||
|
private @interface ComposedCrossOrigin {
|
||||||
|
String[] origins() default {};
|
||||||
|
String allowCredentials() default "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@ComposedCrossOrigin(origins = "http://foo.com", 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://foo.com", allowCredentials = "true")
|
||||||
|
public void foo() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class TestRequestMappingInfoHandlerMapping extends RequestMappingHandlerMapping {
|
private static class TestRequestMappingInfoHandlerMapping extends RequestMappingHandlerMapping {
|
||||||
|
|
||||||
public void registerHandler(Object handler) {
|
public void registerHandler(Object handler) {
|
||||||
|
@ -358,7 +414,7 @@ public class CrossOriginTests {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||||
RequestMapping annotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
|
RequestMapping annotation = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
|
||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
return new RequestMappingInfo(
|
return new RequestMappingInfo(
|
||||||
new PatternsRequestCondition(annotation.value(), getUrlPathHelper(), getPathMatcher(), true, true),
|
new PatternsRequestCondition(annotation.value(), getUrlPathHelper(), getPathMatcher(), true, true),
|
||||||
|
|
Loading…
Reference in New Issue