/* * Copyright 2002-2016 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 * * http://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.Arrays; import java.util.Collections; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.junit.Test; import org.springframework.beans.MutablePropertyValues; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 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 static org.junit.Assert.*; import static org.springframework.web.servlet.HandlerMapping.*; /** * Unit tests for {@link HandlerMappingIntrospector}. * * @author Rossen Stoyanchev * @since 4.3.1 */ 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(); List<?> expected = Arrays.asList(cxt.getBean("hmA"), cxt.getBean("hmB"), cxt.getBean("hmC")); List<HandlerMapping> actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); assertEquals(expected, actual); } @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(); List<?> expected = Arrays.asList(cxt.getBean("hmC"), cxt.getBean("hmB"), cxt.getBean("hmA")); List<HandlerMapping> actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); assertEquals(expected, actual); } @Test @SuppressWarnings("deprecation") public void defaultHandlerMappings() throws Exception { StaticWebApplicationContext cxt = new StaticWebApplicationContext(); cxt.refresh(); List<HandlerMapping> actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); assertEquals(2, actual.size()); assertEquals(BeanNameUrlHandlerMapping.class, actual.get(0).getClass()); assertEquals(RequestMappingHandlerMapping.class, actual.get(1).getClass()); } @Test public void getMatchable() throws Exception { MutablePropertyValues pvs = new MutablePropertyValues( Collections.singletonMap("urlMap", Collections.singletonMap("/path", new Object()))); StaticWebApplicationContext cxt = new StaticWebApplicationContext(); cxt.registerSingleton("hm", SimpleUrlHandlerMapping.class, pvs); cxt.refresh(); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/path"); MatchableHandlerMapping hm = new HandlerMappingIntrospector(cxt).getMatchableHandlerMapping(request); assertEquals(cxt.getBean("hm"), hm); assertNull("Attributes changes not ignored", request.getAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE)); } @Test(expected = IllegalStateException.class) public void getMatchableWhereHandlerMappingDoesNotImplementMatchableInterface() throws Exception { StaticWebApplicationContext cxt = new StaticWebApplicationContext(); cxt.registerSingleton("hm1", TestHandlerMapping.class); cxt.refresh(); MockHttpServletRequest request = new MockHttpServletRequest(); new HandlerMappingIntrospector(cxt).getMatchableHandlerMapping(request); } @Test public void getCorsConfigurationPreFlight() throws Exception { AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext(); cxt.register(TestConfig.class); cxt.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 = new HandlerMappingIntrospector(cxt).getCorsConfiguration(request); assertNotNull(corsConfig); assertEquals(Collections.singletonList("http://localhost:9000"), corsConfig.getAllowedOrigins()); assertEquals(Collections.singletonList("POST"), corsConfig.getAllowedMethods()); } @Test public void getCorsConfigurationActual() throws Exception { AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext(); cxt.register(TestConfig.class); cxt.refresh(); MockHttpServletRequest request = new MockHttpServletRequest("POST", "/path"); request.addHeader("Origin", "http://localhost:9000"); CorsConfiguration corsConfig = new HandlerMappingIntrospector(cxt).getCorsConfiguration(request); assertNotNull(corsConfig); assertEquals(Collections.singletonList("http://localhost:9000"), corsConfig.getAllowedOrigins()); assertEquals(Collections.singletonList("POST"), corsConfig.getAllowedMethods()); } private static class TestHandlerMapping implements HandlerMapping { @Override public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { return new HandlerExecutionChain(new Object()); } } @Configuration @SuppressWarnings({"WeakerAccess", "unused"}) static class TestConfig { @Bean public RequestMappingHandlerMapping handlerMapping() { return new RequestMappingHandlerMapping(); } @Bean public TestController testController() { return new TestController(); } } @CrossOrigin("http://localhost:9000") @Controller private static class TestController { @PostMapping("/path") public void handle() { } } }