Skip to content

Commit 0ad59dd

Browse files
committed
Merge pull request #877 from nithril/SPR-13468
* SPR-13468: Support @crossorigin as a merged composed annotation
2 parents 74b0511 + e4c0859 commit 0ad59dd

File tree

2 files changed

+65
-9
lines changed

2 files changed

+65
-9
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,8 @@ protected String[] resolveEmbeddedValuesInPatterns(String[] patterns) {
286286
@Override
287287
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
288288
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
289-
CrossOrigin typeAnnotation = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), CrossOrigin.class);
290-
CrossOrigin methodAnnotation = AnnotationUtils.findAnnotation(method, CrossOrigin.class);
289+
CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), CrossOrigin.class);
290+
CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);
291291

292292
if (typeAnnotation == null && methodAnnotation == null) {
293293
return null;

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/CrossOriginTests.java

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package org.springframework.web.servlet.mvc.method.annotation;
1818

19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
1923
import java.lang.reflect.Method;
2024
import java.util.Arrays;
2125

@@ -25,6 +29,7 @@
2529
import org.junit.rules.ExpectedException;
2630

2731
import org.springframework.beans.DirectFieldAccessor;
32+
import org.springframework.core.annotation.AnnotatedElementUtils;
2833
import org.springframework.core.annotation.AnnotationUtils;
2934
import org.springframework.http.HttpHeaders;
3035
import org.springframework.mock.web.test.MockHttpServletRequest;
@@ -53,6 +58,7 @@
5358
*
5459
* @author Sebastien Deleuze
5560
* @author Sam Brannen
61+
* @author Nicolas Labrot
5662
*/
5763
public class CrossOriginTests {
5864

@@ -79,17 +85,15 @@ public void noAnnotationWithoutOrigin() throws Exception {
7985
this.handlerMapping.registerHandler(new MethodLevelController());
8086
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/no");
8187
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
82-
CorsConfiguration config = getCorsConfiguration(chain, false);
83-
assertNull(config);
88+
assertNull(getCorsConfiguration(chain, false));
8489
}
8590

8691
@Test // SPR-12931
8792
public void noAnnotationWithOrigin() throws Exception {
8893
this.handlerMapping.registerHandler(new MethodLevelController());
8994
this.request.setRequestURI("/no");
9095
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
91-
CorsConfiguration config = getCorsConfiguration(chain, false);
92-
assertNull(config);
96+
assertNull(getCorsConfiguration(chain, false));
9397
}
9498

9599
@Test // SPR-12931
@@ -98,8 +102,7 @@ public void noAnnotationPostWithOrigin() throws Exception {
98102
this.request.setMethod("POST");
99103
this.request.setRequestURI("/no");
100104
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
101-
CorsConfiguration config = getCorsConfiguration(chain, false);
102-
assertNull(config);
105+
assertNull(getCorsConfiguration(chain, false));
103106
}
104107

105108
@Test
@@ -180,6 +183,32 @@ public void classLevel() throws Exception {
180183
assertTrue(config.getAllowCredentials());
181184
}
182185

186+
@Test // SPR-13468
187+
public void classLevelComposedAnnotation() throws Exception {
188+
this.handlerMapping.registerHandler(new ClassLevelMappingWithComposedAnnotation());
189+
190+
this.request.setRequestURI("/foo");
191+
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
192+
CorsConfiguration config = getCorsConfiguration(chain, false);
193+
assertNotNull(config);
194+
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
195+
assertArrayEquals(new String[]{"http://foo.com"}, config.getAllowedOrigins().toArray());
196+
assertTrue(config.getAllowCredentials());
197+
}
198+
199+
@Test // SPR-13468
200+
public void methodLevelComposedAnnotation() throws Exception {
201+
this.handlerMapping.registerHandler(new MethodLevelMappingWithComposedAnnotation());
202+
203+
this.request.setRequestURI("/foo");
204+
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
205+
CorsConfiguration config = getCorsConfiguration(chain, false);
206+
assertNotNull(config);
207+
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
208+
assertArrayEquals(new String[]{"http://foo.com"}, config.getAllowedOrigins().toArray());
209+
assertTrue(config.getAllowCredentials());
210+
}
211+
183212
@Test
184213
public void preFlightRequest() throws Exception {
185214
this.handlerMapping.registerHandler(new MethodLevelController());
@@ -345,6 +374,33 @@ public void baz() {
345374

346375
}
347376

377+
@Target({ElementType.METHOD, ElementType.TYPE})
378+
@Retention(RetentionPolicy.RUNTIME)
379+
@CrossOrigin
380+
private @interface ComposedCrossOrigin {
381+
String[] origins() default {};
382+
String allowCredentials() default "";
383+
}
384+
385+
@Controller
386+
@ComposedCrossOrigin(origins = "http://foo.com", allowCredentials = "true")
387+
private static class ClassLevelMappingWithComposedAnnotation {
388+
389+
@RequestMapping(path = "/foo", method = RequestMethod.GET)
390+
public void foo() {
391+
}
392+
}
393+
394+
395+
@Controller
396+
private static class MethodLevelMappingWithComposedAnnotation {
397+
398+
@RequestMapping(path = "/foo", method = RequestMethod.GET)
399+
@ComposedCrossOrigin(origins = "http://foo.com", allowCredentials = "true")
400+
public void foo() {
401+
}
402+
}
403+
348404
private static class TestRequestMappingInfoHandlerMapping extends RequestMappingHandlerMapping {
349405

350406
public void registerHandler(Object handler) {
@@ -358,7 +414,7 @@ protected boolean isHandler(Class<?> beanType) {
358414

359415
@Override
360416
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
361-
RequestMapping annotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
417+
RequestMapping annotation = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
362418
if (annotation != null) {
363419
return new RequestMappingInfo(
364420
new PatternsRequestCondition(annotation.value(), getUrlPathHelper(), getPathMatcher(), true, true),

0 commit comments

Comments
 (0)