Method level only, empty RequestMapping matches "" and "/"
Closes gh-30293
This commit is contained in:
parent
3fb98b6a97
commit
bbab4faf7a
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -48,15 +48,12 @@ public class DefaultControllerSpecTests {
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectStatus().isOk()
|
.expectStatus().isOk()
|
||||||
.expectBody(String.class).isEqualTo("Success");
|
.expectBody(String.class).isEqualTo("Success");
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void controllerEmptyPath() {
|
|
||||||
new DefaultControllerSpec(new MyController()).build()
|
new DefaultControllerSpec(new MyController()).build()
|
||||||
.get().uri("")
|
.get().uri("")
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectStatus().isOk()
|
.expectStatus().isOk()
|
||||||
.expectBody(String.class).isEqualTo("Success empty path");
|
.expectBody(String.class).isEqualTo("Success");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -121,19 +118,15 @@ public class DefaultControllerSpecTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
@RestController
|
@RestController
|
||||||
private static class MyController {
|
private static class MyController {
|
||||||
|
|
||||||
@GetMapping("/")
|
@GetMapping
|
||||||
public String handleRootPath() {
|
public String handleRootPath() {
|
||||||
return "Success";
|
return "Success";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
public String handleEmptyPath() {
|
|
||||||
return "Success empty path";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/exception")
|
@GetMapping("/exception")
|
||||||
public void handleWithError() {
|
public void handleWithError() {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
|
|
@ -89,8 +89,12 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
||||||
return " || ";
|
return " || ";
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isEmptyPathMapping() {
|
/**
|
||||||
return this.patterns == EMPTY_PATH_PATTERN;
|
* Whether the condition is the "" (empty path) mapping.
|
||||||
|
* @since 6.0.10
|
||||||
|
*/
|
||||||
|
public boolean isEmptyPathMapping() {
|
||||||
|
return (this.patterns == EMPTY_PATH_PATTERN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -153,6 +153,9 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||||
if (typeInfo != null) {
|
if (typeInfo != null) {
|
||||||
info = typeInfo.combine(info);
|
info = typeInfo.combine(info);
|
||||||
}
|
}
|
||||||
|
if (info.getPatternsCondition().isEmptyPathMapping()) {
|
||||||
|
info = info.mutate().paths("", "/").options(this.config).build();
|
||||||
|
}
|
||||||
for (Map.Entry<String, Predicate<Class<?>>> entry : this.pathPrefixes.entrySet()) {
|
for (Map.Entry<String, Predicate<Class<?>>> entry : this.pathPrefixes.entrySet()) {
|
||||||
if (entry.getValue().test(handlerType)) {
|
if (entry.getValue().test(handlerType)) {
|
||||||
String prefix = entry.getKey();
|
String prefix = entry.getKey();
|
||||||
|
|
|
@ -61,6 +61,17 @@ class RequestMappingIntegrationTests extends AbstractRequestMappingIntegrationTe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ParameterizedHttpServerTest // gh-30293
|
||||||
|
void emptyMapping(HttpServer httpServer) throws Exception {
|
||||||
|
startServer(httpServer);
|
||||||
|
|
||||||
|
String url = "http://localhost:" + this.port;
|
||||||
|
assertThat(getRestTemplate().getForObject(url, String.class)).isEqualTo("root");
|
||||||
|
|
||||||
|
url += "/";
|
||||||
|
assertThat(getRestTemplate().getForObject(url, String.class)).isEqualTo("root");
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedHttpServerTest
|
@ParameterizedHttpServerTest
|
||||||
void httpHead(HttpServer httpServer) throws Exception {
|
void httpHead(HttpServer httpServer) throws Exception {
|
||||||
startServer(httpServer);
|
startServer(httpServer);
|
||||||
|
@ -106,6 +117,11 @@ class RequestMappingIntegrationTests extends AbstractRequestMappingIntegrationTe
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static class TestRestController {
|
private static class TestRestController {
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String get() {
|
||||||
|
return "root";
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/text")
|
@GetMapping("/text")
|
||||||
public String textGet() {
|
public String textGet() {
|
||||||
return "Foo";
|
return "Foo";
|
||||||
|
|
|
@ -255,6 +255,16 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||||
pprc.getPatternValues() : ((PatternsRequestCondition) condition).getPatterns());
|
pprc.getPatternValues() : ((PatternsRequestCondition) condition).getPatterns());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the request mapping has an empty URL path mapping.
|
||||||
|
* @since 6.0.10
|
||||||
|
*/
|
||||||
|
public boolean isEmptyMapping() {
|
||||||
|
RequestCondition<?> condition = getActivePatternsCondition();
|
||||||
|
return (condition instanceof PathPatternsRequestCondition pprc ?
|
||||||
|
pprc.isEmptyPathMapping() : ((PatternsRequestCondition) condition).isEmptyPathMapping());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the HTTP request methods of this {@link RequestMappingInfo};
|
* Return the HTTP request methods of this {@link RequestMappingInfo};
|
||||||
* or instance with 0 request methods (never {@code null}).
|
* or instance with 0 request methods (never {@code null}).
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -305,6 +305,9 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||||
if (typeInfo != null) {
|
if (typeInfo != null) {
|
||||||
info = typeInfo.combine(info);
|
info = typeInfo.combine(info);
|
||||||
}
|
}
|
||||||
|
if (info.isEmptyMapping()) {
|
||||||
|
info = info.mutate().paths("", "/").options(this.config).build();
|
||||||
|
}
|
||||||
String prefix = getPathPrefix(handlerType);
|
String prefix = getPathPrefix(handlerType);
|
||||||
if (prefix != null) {
|
if (prefix != null) {
|
||||||
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
|
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
|
||||||
|
|
|
@ -192,7 +192,16 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
||||||
request.setServletPath("");
|
request.setServletPath("");
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
getServlet().service(request, response);
|
getServlet().service(request, response);
|
||||||
|
|
||||||
assertThat(response.getContentAsString()).isEqualTo("test");
|
assertThat(response.getContentAsString()).isEqualTo("test");
|
||||||
|
|
||||||
|
// gh-30293
|
||||||
|
request = new MockHttpServletRequest("GET", "/");
|
||||||
|
response = new MockHttpServletResponse();
|
||||||
|
getServlet().service(request, response);
|
||||||
|
|
||||||
|
assertThat(response.getContentAsString()).isEqualTo("test");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PathPatternsParameterizedTest
|
@PathPatternsParameterizedTest
|
||||||
|
|
Loading…
Reference in New Issue