7 changed files with 554 additions and 11 deletions
@ -0,0 +1,192 @@ |
|||||||
|
/* |
||||||
|
* 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.support; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Properties; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletRequestWrapper; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanFactoryUtils; |
||||||
|
import org.springframework.context.ApplicationContext; |
||||||
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator; |
||||||
|
import org.springframework.core.io.ClassPathResource; |
||||||
|
import org.springframework.core.io.Resource; |
||||||
|
import org.springframework.core.io.support.PropertiesLoaderUtils; |
||||||
|
import org.springframework.util.ClassUtils; |
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
import org.springframework.web.cors.CorsConfiguration; |
||||||
|
import org.springframework.web.cors.CorsConfigurationSource; |
||||||
|
import org.springframework.web.servlet.DispatcherServlet; |
||||||
|
import org.springframework.web.servlet.HandlerExecutionChain; |
||||||
|
import org.springframework.web.servlet.HandlerInterceptor; |
||||||
|
import org.springframework.web.servlet.HandlerMapping; |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper class to get information from the {@code HandlerMapping} that would |
||||||
|
* serve a specific request. |
||||||
|
* |
||||||
|
* <p>Provides the following methods: |
||||||
|
* <ul> |
||||||
|
* <li>{@link #getMatchableHandlerMapping} -- obtain a {@code HandlerMapping} |
||||||
|
* to check request-matching criteria against. |
||||||
|
* <li>{@link #getCorsConfiguration} -- obtain the CORS configuration for the |
||||||
|
* request. |
||||||
|
* </ul> |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @since 4.3 |
||||||
|
*/ |
||||||
|
public class HandlerMappingIntrospector implements CorsConfigurationSource { |
||||||
|
|
||||||
|
private final List<HandlerMapping> handlerMappings; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor that detects the configured {@code HandlerMapping}s in the |
||||||
|
* given {@code ApplicationContext} or falling back on |
||||||
|
* "DispatcherServlet.properties" like the {@code DispatcherServlet}. |
||||||
|
*/ |
||||||
|
public HandlerMappingIntrospector(ApplicationContext context) { |
||||||
|
this.handlerMappings = initHandlerMappings(context); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static List<HandlerMapping> initHandlerMappings(ApplicationContext context) { |
||||||
|
|
||||||
|
Map<String, HandlerMapping> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( |
||||||
|
context, HandlerMapping.class, true, false); |
||||||
|
|
||||||
|
if (!beans.isEmpty()) { |
||||||
|
List<HandlerMapping> mappings = new ArrayList<HandlerMapping>(beans.values()); |
||||||
|
AnnotationAwareOrderComparator.sort(mappings); |
||||||
|
return mappings; |
||||||
|
} |
||||||
|
|
||||||
|
return initDefaultHandlerMappings(context); |
||||||
|
} |
||||||
|
|
||||||
|
private static List<HandlerMapping> initDefaultHandlerMappings(ApplicationContext context) { |
||||||
|
Properties props; |
||||||
|
String path = "DispatcherServlet.properties"; |
||||||
|
try { |
||||||
|
Resource resource = new ClassPathResource(path, DispatcherServlet.class); |
||||||
|
props = PropertiesLoaderUtils.loadProperties(resource); |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
throw new IllegalStateException("Could not load '" + path + "': " + ex.getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
String value = props.getProperty(HandlerMapping.class.getName()); |
||||||
|
String[] names = StringUtils.commaDelimitedListToStringArray(value); |
||||||
|
List<HandlerMapping> result = new ArrayList<HandlerMapping>(names.length); |
||||||
|
for (String name : names) { |
||||||
|
try { |
||||||
|
Class<?> clazz = ClassUtils.forName(name, DispatcherServlet.class.getClassLoader()); |
||||||
|
Object mapping = context.getAutowireCapableBeanFactory().createBean(clazz); |
||||||
|
result.add((HandlerMapping) mapping); |
||||||
|
} |
||||||
|
catch (ClassNotFoundException ex) { |
||||||
|
throw new IllegalStateException("Could not find default HandlerMapping [" + name + "]"); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Return the configured HandlerMapping's. |
||||||
|
*/ |
||||||
|
public List<HandlerMapping> getHandlerMappings() { |
||||||
|
return this.handlerMappings; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Find the {@link HandlerMapping} that would handle the given request and |
||||||
|
* return it as a {@link MatchableHandlerMapping} that can be used to |
||||||
|
* test request-matching criteria. If the matching HandlerMapping is not an |
||||||
|
* instance of {@link MatchableHandlerMapping}, an IllegalStateException is |
||||||
|
* raised. |
||||||
|
* |
||||||
|
* @param request the current request |
||||||
|
* @return the resolved matcher, or {@code null} |
||||||
|
* @throws Exception if any of the HandlerMapping's raise an exception |
||||||
|
*/ |
||||||
|
public MatchableHandlerMapping getMatchableHandlerMapping(HttpServletRequest request) throws Exception { |
||||||
|
HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request); |
||||||
|
for (HandlerMapping handlerMapping : this.handlerMappings) { |
||||||
|
Object handler = handlerMapping.getHandler(wrapper); |
||||||
|
if (handler == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (handlerMapping instanceof MatchableHandlerMapping) { |
||||||
|
return ((MatchableHandlerMapping) handlerMapping); |
||||||
|
} |
||||||
|
throw new IllegalStateException("HandlerMapping is not a MatchableHandlerMapping"); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { |
||||||
|
HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request); |
||||||
|
for (HandlerMapping handlerMapping : this.handlerMappings) { |
||||||
|
HandlerExecutionChain handler = null; |
||||||
|
try { |
||||||
|
handler = handlerMapping.getHandler(wrapper); |
||||||
|
} |
||||||
|
catch (Exception ex) { |
||||||
|
// Ignore
|
||||||
|
} |
||||||
|
if (handler == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (handler.getInterceptors() != null) { |
||||||
|
for (HandlerInterceptor interceptor : handler.getInterceptors()) { |
||||||
|
if (interceptor instanceof CorsConfigurationSource) { |
||||||
|
return ((CorsConfigurationSource) interceptor).getCorsConfiguration(wrapper); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (handler.getHandler() instanceof CorsConfigurationSource) { |
||||||
|
return ((CorsConfigurationSource) handler.getHandler()).getCorsConfiguration(wrapper); |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Request wrapper that ignores request attribute changes. |
||||||
|
*/ |
||||||
|
private static class RequestAttributeChangeIgnoringWrapper extends HttpServletRequestWrapper { |
||||||
|
|
||||||
|
|
||||||
|
private RequestAttributeChangeIgnoringWrapper(HttpServletRequest request) { |
||||||
|
super(request); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setAttribute(String name, Object value) { |
||||||
|
// Ignore attribute change
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* 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.support; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
|
||||||
|
import org.springframework.web.servlet.HandlerMapping; |
||||||
|
|
||||||
|
/** |
||||||
|
* Additional interface that a {@link HandlerMapping} can implement to expose |
||||||
|
* a request matching API aligned with its internal request matching |
||||||
|
* configuration and implementation. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @since 4.3 |
||||||
|
* @see HandlerMappingIntrospector |
||||||
|
*/ |
||||||
|
public interface MatchableHandlerMapping { |
||||||
|
|
||||||
|
/** |
||||||
|
* Whether the given request matches the request criteria. |
||||||
|
* @param request the current request |
||||||
|
* @param pattern the pattern to match |
||||||
|
* @return the result from request matching or {@code null} |
||||||
|
*/ |
||||||
|
RequestMatchResult match(HttpServletRequest request, String pattern); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,77 @@ |
|||||||
|
/* |
||||||
|
* 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.support; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.util.PathMatcher; |
||||||
|
|
||||||
|
/** |
||||||
|
* Container for the result from request pattern matching via |
||||||
|
* {@link MatchableHandlerMapping} with a method to further extract URI template |
||||||
|
* variables from the pattern. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @since 4.3 |
||||||
|
*/ |
||||||
|
public class RequestMatchResult { |
||||||
|
|
||||||
|
private final String matchingPattern; |
||||||
|
|
||||||
|
private final String lookupPath; |
||||||
|
|
||||||
|
private final PathMatcher pathMatcher; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create an instance with a matching pattern. |
||||||
|
* @param matchingPattern the matching pattern, possibly not the same as the |
||||||
|
* input pattern, e.g. inputPattern="/foo" and matchingPattern="/foo/". |
||||||
|
* @param lookupPath the lookup path extracted from the request |
||||||
|
* @param pathMatcher the PathMatcher used |
||||||
|
*/ |
||||||
|
public RequestMatchResult(String matchingPattern, String lookupPath, PathMatcher pathMatcher) { |
||||||
|
Assert.hasText(matchingPattern, "'matchingPattern' is required"); |
||||||
|
Assert.hasText(lookupPath, "'lookupPath' is required"); |
||||||
|
Assert.notNull(pathMatcher, "'pathMatcher' is required"); |
||||||
|
this.matchingPattern = matchingPattern; |
||||||
|
this.lookupPath = lookupPath; |
||||||
|
this.pathMatcher = pathMatcher; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Whether the pattern was matched to the request. |
||||||
|
*/ |
||||||
|
public boolean isMatch() { |
||||||
|
return (this.matchingPattern != null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Extract URI template variables from the matching pattern as defined in |
||||||
|
* {@link PathMatcher#extractUriTemplateVariables}. |
||||||
|
* @return a map with URI template variables |
||||||
|
*/ |
||||||
|
public Map<String, String> extractUriTemplateVariables() { |
||||||
|
if (!isMatch()) { |
||||||
|
return Collections.<String, String>emptyMap(); |
||||||
|
} |
||||||
|
return this.pathMatcher.extractUriTemplateVariables(this.matchingPattern, this.lookupPath); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,190 @@ |
|||||||
|
/* |
||||||
|
* 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.support; |
||||||
|
|
||||||
|
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.handler.BeanNameUrlHandlerMapping; |
||||||
|
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; |
||||||
|
import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping; |
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; |
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertNotNull; |
||||||
|
import static org.junit.Assert.assertNull; |
||||||
|
import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests for {@link HandlerMappingIntrospector}. |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
*/ |
||||||
|
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(DefaultAnnotationHandlerMapping.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() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue