Merge branch '7.0.x'

This commit is contained in:
rstoyanchev
2026-06-22 13:50:10 +01:00
17 changed files with 198 additions and 180 deletions
@@ -74,7 +74,8 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry {
/** Static evaluation context to reuse. */
private static final EvaluationContext messageEvalContext =
SimpleEvaluationContext.forPropertyAccessors(new SimpMessageHeaderPropertyAccessor()).build();
SimpleEvaluationContext.forPropertyAccessors(new SimpMessageHeaderPropertyAccessor())
.withAssignmentDisabled().build();
private PathMatcher pathMatcher = new AntPathMatcher();
@@ -456,7 +456,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
accessor.setLogin(this.systemLogin);
accessor.setPasscode(this.systemPasscode);
accessor.setHeartbeat(this.systemHeartbeatSendInterval, this.systemHeartbeatReceiveInterval);
accessor.setHost(getVirtualHost() != null ? getVirtualHost() : getRelayHost());
accessor.setHost(getVirtualHost() != null ? getVirtualHost() : null);
accessor.setSessionId(SYSTEM_SESSION_ID);
if (logger.isDebugEnabled()) {
logger.debug("Forwarding " + accessor.getShortLogMessage(EMPTY_PAYLOAD));
@@ -579,7 +579,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
stompHeaderAccessor = (stompHeaderAccessor.isMutable() ? stompHeaderAccessor : StompHeaderAccessor.wrap(message));
stompHeaderAccessor.setLogin(this.clientLogin);
stompHeaderAccessor.setPasscode(this.clientPasscode);
stompHeaderAccessor.setHost(getVirtualHost() != null ? getVirtualHost() : getRelayHost());
stompHeaderAccessor.setHost(getVirtualHost() != null ? getVirtualHost() : null);
RelayConnectionHandler handler = new RelayConnectionHandler(sessionId, stompHeaderAccessor);
this.connectionHandlers.put(sessionId, handler);
this.stats.incrementConnectCount();
@@ -98,6 +98,27 @@ class StompBrokerRelayMessageHandlerTests {
assertThat(headers2.getHost()).isEqualTo("ABC");
}
@Test
void virtualHostDefault() {
Message<byte[]> connectMessage = connectMessage("sess1", "joe");
MessageHeaderAccessor.getAccessor(connectMessage, StompHeaderAccessor.class).setHost("ABC");
this.brokerRelay.start();
this.brokerRelay.handleMessage(connectMessage("sess1", "joe"));
assertThat(this.tcpClient.getSentMessages()).hasSize(2);
StompHeaderAccessor headers1 = this.tcpClient.getSentHeaders(0);
assertThat(headers1.getCommand()).isEqualTo(StompCommand.CONNECT);
assertThat(headers1.getSessionId()).isEqualTo(StompBrokerRelayMessageHandler.SYSTEM_SESSION_ID);
assertThat(headers1.getHost()).isNull();
StompHeaderAccessor headers2 = this.tcpClient.getSentHeaders(1);
assertThat(headers2.getCommand()).isEqualTo(StompCommand.CONNECT);
assertThat(headers2.getSessionId()).isEqualTo("sess1");
assertThat(headers2.getHost()).isNull();
}
@Test
void loginAndPasscode() {
this.brokerRelay.setSystemLogin("syslogin");
@@ -135,19 +135,25 @@ abstract class ReactorUriHelper {
if (c == '/' || c == '?' || c == '#') {
break;
}
if (c == ':' && (i + 2 < length)) {
if (uri.charAt(i + 1) == '/' && uri.charAt(i + 2) == '/') {
for (int j = i + 3; j < length; j++) {
c = uri.charAt(j);
if (c == '/' || c == '?' || c == '#') {
builder.append(uri, j, length);
return;
}
if (hasAuthority(uri, c, i, length)) {
for (i = i + 3; i < length; i++) {
c = uri.charAt(i);
if (c == '/' || c == '?' || c == '#') {
builder.append(uri, i, length);
return;
}
return;
}
return;
}
}
if (length > 0 && uri.charAt(0) != '/') {
builder.append('/');
}
builder.append(uri);
}
private static boolean hasAuthority(String uri, char c, int i, int length) {
return (c == ':' && (i + 2 < length) && (uri.charAt(i + 1) == '/' && uri.charAt(i + 2) == '/'));
}
}
@@ -148,9 +148,11 @@ public abstract class AbstractMappingContentNegotiationStrategy extends MappingM
throws HttpMediaTypeNotAcceptableException {
if (!isUseRegisteredExtensionsOnly()) {
Optional<MediaType> mediaType = MediaTypeFactory.getMediaType("file." + key);
if (mediaType.isPresent()) {
return mediaType.get();
if (key.indexOf('.') == -1) {
Optional<MediaType> mediaType = MediaTypeFactory.getMediaType("file." + key);
if (mediaType.isPresent()) {
return mediaType.get();
}
}
}
if (isIgnoreUnknownExtensions()) {
@@ -57,12 +57,7 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
public MappingMediaTypeFileExtensionResolver(@Nullable Map<String, MediaType> mediaTypes) {
if (mediaTypes != null) {
Set<String> allFileExtensions = CollectionUtils.newHashSet(mediaTypes.size());
mediaTypes.forEach((extension, mediaType) -> {
String lowerCaseExtension = extension.toLowerCase(Locale.ROOT);
this.mediaTypes.put(lowerCaseExtension, mediaType);
addFileExtension(mediaType, lowerCaseExtension);
allFileExtensions.add(lowerCaseExtension);
});
mediaTypes.forEach(this::addMapping);
this.allFileExtensions.addAll(allFileExtensions);
}
}
@@ -79,19 +74,15 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
/**
* Map an extension to a MediaType. Ignore if extension already mapped.
*/
protected void addMapping(String extension, MediaType mediaType) {
MediaType previous = this.mediaTypes.putIfAbsent(extension, mediaType);
protected void addMapping(String key, MediaType mediaType) {
key = key.toLowerCase(Locale.ROOT);
MediaType previous = this.mediaTypes.putIfAbsent(key, mediaType);
if (previous == null) {
addFileExtension(mediaType, extension);
this.allFileExtensions.add(extension);
this.fileExtensions.computeIfAbsent(mediaType, k -> new CopyOnWriteArrayList<>()).add(key);
this.allFileExtensions.add(key);
}
}
private void addFileExtension(MediaType mediaType, String extension) {
this.fileExtensions.computeIfAbsent(mediaType, key -> new CopyOnWriteArrayList<>())
.add(extension);
}
@Override
public List<String> resolveFileExtensions(MediaType mediaType) {
@@ -453,221 +453,172 @@ public class StandardServletAsyncWebRequest extends ServletWebRequest implements
@Override
public void flush() {
invokeWithLock(this.delegate::flush);
}
private void invokeWithLock(Runnable runnable) {
int level = this.asyncWebRequest.tryObtainLock();
if (level > -1) {
try {
this.delegate.flush();
runnable.run();
}
finally {
releaseLock(level);
if (level > 0) {
this.asyncWebRequest.stateLock.unlock();
}
}
}
}
@Override
public void close() {
int level = this.asyncWebRequest.tryObtainLock();
if (level > -1) {
try {
this.delegate.close();
}
finally {
releaseLock(level);
}
}
}
@Override
public boolean checkError() {
return this.delegate.checkError();
invokeWithLock(this.delegate::close);
}
@Override
public void write(int c) {
int level = this.asyncWebRequest.tryObtainLock();
if (level > -1) {
try {
this.delegate.write(c);
}
finally {
releaseLock(level);
}
}
invokeWithLock(() -> this.delegate.write(c));
}
@Override
public void write(char[] buf, int off, int len) {
int level = this.asyncWebRequest.tryObtainLock();
if (level > -1) {
try {
this.delegate.write(buf, off, len);
}
finally {
releaseLock(level);
}
}
invokeWithLock(() -> this.delegate.write(buf, off, len));
}
@Override
public void write(char[] buf) {
this.delegate.write(buf);
write(buf, 0, buf.length);
}
@Override
public void write(String s, int off, int len) {
int level = this.asyncWebRequest.tryObtainLock();
if (level > -1) {
try {
this.delegate.write(s, off, len);
}
finally {
releaseLock(level);
}
}
invokeWithLock(() -> this.delegate.write(s, off, len));
}
@Override
public void write(String s) {
this.delegate.write(s);
}
private void releaseLock(int level) {
if (level > 0) {
this.asyncWebRequest.stateLock.unlock();
}
write(s, 0, s.length());
}
// Plain delegates
@Override
public void print(boolean b) {
this.delegate.print(b);
write(String.valueOf(b));
}
@Override
public void print(char c) {
this.delegate.print(c);
write(c);
}
@Override
public void print(int i) {
this.delegate.print(i);
write(String.valueOf(i));
}
@Override
public void print(long l) {
this.delegate.print(l);
write(String.valueOf(l));
}
@Override
public void print(float f) {
this.delegate.print(f);
write(String.valueOf(f));
}
@Override
public void print(double d) {
this.delegate.print(d);
write(String.valueOf(d));
}
@Override
public void print(char[] s) {
this.delegate.print(s);
write(s);
}
@Override
public void print(String s) {
this.delegate.print(s);
write(String.valueOf(s));
}
@Override
public void print(Object obj) {
this.delegate.print(obj);
write(String.valueOf(obj));
}
@Override
public void println() {
this.delegate.println();
invokeWithLock(this.delegate::println);
}
@Override
public void println(boolean x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public void println(char x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public void println(int x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public void println(long x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public void println(float x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public void println(double x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public void println(char[] x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public void println(String x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public void println(Object x) {
this.delegate.println(x);
invokeWithLock(() -> this.delegate.println(x));
}
@Override
public PrintWriter printf(String format, Object... args) {
return this.delegate.printf(format, args);
return format(format, args);
}
@Override
public PrintWriter printf(Locale l, String format, Object... args) {
return this.delegate.printf(l, format, args);
return format(format, args);
}
@Override
public PrintWriter format(String format, Object... args) {
return this.delegate.format(format, args);
invokeWithLock(() -> this.delegate.format(format, args));
return this;
}
@Override
public PrintWriter format(Locale l, String format, Object... args) {
return this.delegate.format(l, format, args);
invokeWithLock(() -> this.delegate.format(format, args));
return this;
}
@Override
public PrintWriter append(CharSequence csq) {
return this.delegate.append(csq);
}
@Override
public PrintWriter append(CharSequence csq, int start, int end) {
return this.delegate.append(csq, start, end);
}
@Override
public PrintWriter append(char c) {
return this.delegate.append(c);
}
}
@@ -35,10 +35,11 @@ import static org.mockito.Mockito.mock;
*/
class ReactorUriHelperTests {
private final HttpServerRequest nettyRequest = mock();
@Test
void hostnameWithZoneId() throws URISyntaxException {
HttpServerRequest nettyRequest = mock();
given(nettyRequest.scheme()).willReturn("http");
given(nettyRequest.hostName()).willReturn("fe80::a%en1");
given(nettyRequest.hostPort()).willReturn(80);
@@ -50,7 +51,36 @@ class ReactorUriHelperTests {
.hasPort(-1)
.hasPath("/")
.hasToString("http://[fe80::a%25en1]/");
}
@Test
void requestUriWithScheme() throws URISyntaxException {
given(nettyRequest.scheme()).willReturn("http");
given(nettyRequest.hostName()).willReturn("example.org");
given(nettyRequest.hostPort()).willReturn(80);
given(nettyRequest.uri()).willReturn("http://example.org/path");
URI uri = ReactorUriHelper.createUri(nettyRequest);
assertThat(uri).hasScheme("http")
.hasHost("example.org")
.hasPort(-1)
.hasPath("/path")
.hasToString("http://example.org/path");
}
@Test
void requestUriWithoutLeadingSlash() throws URISyntaxException {
given(nettyRequest.scheme()).willReturn("http");
given(nettyRequest.hostName()).willReturn("example.org");
given(nettyRequest.hostPort()).willReturn(80);
given(nettyRequest.uri()).willReturn("foo/bar");
URI uri = ReactorUriHelper.createUri(nettyRequest);
assertThat(uri).hasScheme("http")
.hasHost("example.org")
.hasPort(-1)
.hasPath("/foo/bar")
.hasToString("http://example.org/foo/bar");
}
@ParameterizedTest(name = "{displayName}({arguments})")
@@ -61,8 +91,6 @@ class ReactorUriHelperTests {
"'' | /",
})
void forwardedPrefix(String forwardedPrefixHeader, String expectedPath) throws URISyntaxException {
HttpServerRequest nettyRequest = mock();
given(nettyRequest.scheme()).willReturn("https");
given(nettyRequest.hostName()).willReturn("localhost");
given(nettyRequest.hostPort()).willReturn(443);
@@ -23,9 +23,11 @@ import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.context.request.NativeWebRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* A test fixture with a test subclass of AbstractMappingContentNegotiationStrategy.
@@ -36,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class MappingContentNegotiationStrategyTests {
@Test
void resolveMediaTypes() throws Exception {
void resolveMediaTypesFromRegisteredExtensions() throws Exception {
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
TestMappingContentNegotiationStrategy strategy = new TestMappingContentNegotiationStrategy("json", mapping);
@@ -47,27 +49,7 @@ class MappingContentNegotiationStrategyTests {
}
@Test
void resolveMediaTypesNoMatch() throws Exception {
Map<String, MediaType> mapping = null;
TestMappingContentNegotiationStrategy strategy = new TestMappingContentNegotiationStrategy("blah", mapping);
List<MediaType> mediaTypes = strategy.resolveMediaTypes(null);
assertThat(mediaTypes).isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
}
@Test
void resolveMediaTypesNoKey() throws Exception {
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
TestMappingContentNegotiationStrategy strategy = new TestMappingContentNegotiationStrategy(null, mapping);
List<MediaType> mediaTypes = strategy.resolveMediaTypes(null);
assertThat(mediaTypes).isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
}
@Test
void resolveMediaTypesHandleNoMatch() throws Exception {
void resolveMediaTypesViaFactory() throws Exception {
Map<String, MediaType> mapping = null;
TestMappingContentNegotiationStrategy strategy = new TestMappingContentNegotiationStrategy("xml", mapping);
@@ -77,6 +59,34 @@ class MappingContentNegotiationStrategyTests {
assertThat(mediaTypes.get(0).toString()).isEqualTo("application/xml");
}
@Test
void resolveMediaTypesUnknownKey() {
Map<String, MediaType> mapping = null;
TestMappingContentNegotiationStrategy strategy = new TestMappingContentNegotiationStrategy("blah", mapping);
assertThatThrownBy(() -> strategy.resolveMediaTypes(null))
.isInstanceOf(HttpMediaTypeNotAcceptableException.class);
}
@Test
void resolveMediaTypesInvalidKey() {
Map<String, MediaType> mapping = null;
TestMappingContentNegotiationStrategy strategy = new TestMappingContentNegotiationStrategy("not.json", mapping);
assertThatThrownBy(() -> strategy.resolveMediaTypes(null))
.isInstanceOf(HttpMediaTypeNotAcceptableException.class);
}
@Test
void resolveMediaTypesNullKey() throws Exception {
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
TestMappingContentNegotiationStrategy strategy = new TestMappingContentNegotiationStrategy(null, mapping);
List<MediaType> mediaTypes = strategy.resolveMediaTypes(null);
assertThat(mediaTypes).isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
}
private static class TestMappingContentNegotiationStrategy extends AbstractMappingContentNegotiationStrategy {
@@ -92,10 +102,6 @@ class MappingContentNegotiationStrategyTests {
return this.extension;
}
@Override
protected MediaType handleNoMatch(NativeWebRequest request, String mappingKey) {
return "xml".equals(mappingKey) ? MediaType.APPLICATION_XML : null;
}
}
}
@@ -68,13 +68,17 @@ class MappingMediaTypeFileExtensionResolverTests {
}
@Test
void allFileExtensions() {
Map<String, MediaType> mappings = new HashMap<>();
mappings.put("json", MediaType.APPLICATION_JSON);
mappings.put("JsOn", MediaType.APPLICATION_JSON);
mappings.put("jSoN", MediaType.APPLICATION_JSON);
void mappingsAreCaseInsensitive() {
Map<String, MediaType> map = new HashMap<>();
map.put("json", MediaType.APPLICATION_JSON);
map.put("JsOn", MediaType.APPLICATION_JSON);
map.put("jSoN", MediaType.APPLICATION_JSON);
MappingMediaTypeFileExtensionResolver resolver = new MappingMediaTypeFileExtensionResolver(map);
map.forEach(resolver::addMapping);
MappingMediaTypeFileExtensionResolver resolver = new MappingMediaTypeFileExtensionResolver(mappings);
assertThat(resolver.getAllFileExtensions()).containsExactly("json");
}
}
@@ -334,10 +334,8 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
logger.trace(exchange.getLogPrefix() + matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
for (Match match : matches) {
if (match.hasCorsConfig()) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
if (matches.stream().allMatch(Match::hasCorsConfig)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
}
else {
@@ -149,7 +149,7 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
if (JettyWebSocketSession.this.handlerCompletionSink != null) {
JettyWebSocketSession.this.handlerCompletionSink.tryEmitError(error);
}
getDelegate().close(StatusCode.SERVER_ERROR, error.getMessage(), Callback.NOOP);
getDelegate().close(StatusCode.SERVER_ERROR, null, Callback.NOOP);
}
void onHandleComplete() {
@@ -131,8 +131,8 @@ class HandlerMethodMappingTests {
@Test // gh-26490
void ambiguousMatchOnPreFlightRequestWithCorsConfig() throws Exception {
this.mapping.registerMapping("/f?o", this.handler, this.method1);
this.mapping.registerMapping("/fo?", this.handler, this.handler.getClass().getMethod("corsHandlerMethod"));
this.mapping.registerMapping("/f?o", this.handler, this.handler.getClass().getMethod("corsHandlerMethod1"));
this.mapping.registerMapping("/fo?", this.handler, this.handler.getClass().getMethod("corsHandlerMethod2"));
MockServerWebExchange exchange = MockServerWebExchange.from(
MockServerHttpRequest.options("https://example.org/foo")
@@ -256,7 +256,12 @@ class HandlerMethodMappingTests {
@RequestMapping
@CrossOrigin(originPatterns = "*")
public void corsHandlerMethod() {
public void corsHandlerMethod1() {
}
@RequestMapping
@CrossOrigin(originPatterns = "*")
public void corsHandlerMethod2() {
}
}
@@ -409,10 +409,8 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
logger.trace(matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(request)) {
for (Match match : matches) {
if (match.hasCorsConfig()) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
if (matches.stream().allMatch(Match::hasCorsConfig)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
}
else {
@@ -28,21 +28,17 @@ import org.springframework.web.util.ServletRequestPathUtils;
/**
* Simple {@code Controller} implementation that transforms the virtual
* path of a URL into a view name and returns that view.
* path of a URL into a view name and returns that view, optionally prepending a
* {@link #setPrefix prefix} and/or appending a {@link #setSuffix suffix}.
*
* <p>Can optionally prepend a {@link #setPrefix prefix} and/or append a
* {@link #setSuffix suffix} to build the viewname from the URL filename.
*
* <p>Find some examples below:
* <p>This is intended for use with individually mapped static content pages
* such as a home page or an index page. See examples below:
* <ol>
* <li>{@code "/index" -> "index"}</li>
* <li>{@code "/index.html" -> "index"}</li>
* <li>{@code "/index.html"} + prefix {@code "pre_"} and suffix {@code "_suf" -> "pre_index_suf"}</li>
* <li>{@code "/products/view.html" -> "products/view"}</li>
* </ol>
*
* <p>Thanks to David Barri for suggesting prefix/suffix support!
*
* @author Alef Arendsen
* @author Juergen Hoeller
* @author Rob Harrop
@@ -35,6 +35,7 @@ import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.resource.ResourceHandlerUtils;
/**
* An extension of Groovy's {@link groovy.text.markup.TemplateConfiguration} and
@@ -223,7 +224,11 @@ public class GroovyMarkupConfigurer extends TemplateConfiguration
@Override
public URL resolveTemplate(String templatePath) throws IOException {
Assert.state(this.classLoader != null, "No template ClassLoader available");
return GroovyMarkupConfigurer.this.resolveTemplate(this.classLoader, templatePath);
String path = ResourceHandlerUtils.normalizeInputPath(templatePath);
if (ResourceHandlerUtils.shouldIgnoreInputPath(path)) {
throw new IOException("Invalid template path:" + templatePath);
}
return GroovyMarkupConfigurer.this.resolveTemplate(this.classLoader, path);
}
}
@@ -142,8 +142,8 @@ class HandlerMethodMappingTests {
@Test // gh-26490
void ambiguousMatchOnPreFlightRequestWithCorsConfig() throws Exception {
this.mapping.registerMapping("/f?o", this.handler, this.method1);
this.mapping.registerMapping("/fo?", this.handler, this.handler.getClass().getMethod("corsHandlerMethod"));
this.mapping.registerMapping("/f?o", this.handler, this.handler.getClass().getMethod("corsHandlerMethod1"));
this.mapping.registerMapping("/fo?", this.handler, this.handler.getClass().getMethod("corsHandlerMethod2"));
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/foo");
request.addHeader(HttpHeaders.ORIGIN, "https://domain.com");
@@ -166,7 +166,7 @@ class HandlerMethodMappingTests {
@Test
void abortInterceptorInPreFlightRequestWithCorsConfig() throws Exception {
this.mapping.registerMapping("/foo", this.handler, this.handler.getClass().getMethod("corsHandlerMethod"));
this.mapping.registerMapping("/foo", this.handler, this.handler.getClass().getMethod("corsHandlerMethod1"));
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/foo");
request.addParameter("abort", "true");
@@ -297,7 +297,7 @@ class HandlerMethodMappingTests {
@Test
void registerCustomHandlerMethod() throws Exception {
this.mapping.setCustomerHandlerMethod(true);
this.mapping.registerMapping("/foo", this.handler, this.handler.getClass().getMethod("corsHandlerMethod"));
this.mapping.registerMapping("/foo", this.handler, this.handler.getClass().getMethod("corsHandlerMethod1"));
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/foo");
request.addParameter("abort", "true");
@@ -418,7 +418,13 @@ class HandlerMethodMappingTests {
@RequestMapping
@CrossOrigin(originPatterns = "*")
public void corsHandlerMethod() {
public void corsHandlerMethod1() {
}
@RequestMapping
@CrossOrigin(originPatterns = "*")
public void corsHandlerMethod2() {
}
}
}