Skip to content

Commit

Permalink
Method level only, empty RequestMapping matches "" and "/"
Browse files Browse the repository at this point in the history
  • Loading branch information
rstoyanchev authored and mdeinum committed Jun 29, 2023
1 parent 60455f4 commit a15f182
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -48,15 +48,12 @@ public void controller() {
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Success");
}

@Test
public void controllerEmptyPath() {
new DefaultControllerSpec(new MyController()).build()
.get().uri("")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Success empty path");
.expectBody(String.class).isEqualTo("Success");
}

@Test
Expand Down Expand Up @@ -121,19 +118,15 @@ public void uriTemplate() {
}


@SuppressWarnings("unused")
@RestController
private static class MyController {

@GetMapping("/")
@GetMapping
public String handleRootPath() {
return "Success";
}

@GetMapping
public String handleEmptyPath() {
return "Success empty path";
}

@GetMapping("/exception")
public void handleWithError() {
throw new IllegalStateException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,12 @@ protected String getToStringInfix() {
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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -153,6 +153,9 @@ protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handler
if (typeInfo != null) {
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()) {
if (entry.getValue().test(handlerType)) {
String prefix = entry.getKey();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ protected ApplicationContext initApplicationContext() {
}


@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
void httpHead(HttpServer httpServer) throws Exception {
startServer(httpServer);
Expand Down Expand Up @@ -106,6 +117,11 @@ static class WebConfig {
@SuppressWarnings("unused")
private static class TestRestController {

@GetMapping
public String get() {
return "root";
}

@GetMapping("/text")
public String textGet() {
return "Foo";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,16 @@ public Set<String> getPatternValues() {
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};
* or instance with 0 request methods (never {@code null}).
Expand Down
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -305,6 +305,9 @@ protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handler
if (typeInfo != null) {
info = typeInfo.combine(info);
}
if (info.isEmptyMapping()) {
info = info.mutate().paths("", "/").options(this.config).build();
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,16 @@ void emptyValueMapping(boolean usePathPatterns) throws Exception {
request.setServletPath("");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);

assertThat(response.getContentAsString()).isEqualTo("test");

// gh-30293
request = new MockHttpServletRequest("GET", "/");
response = new MockHttpServletResponse();
getServlet().service(request, response);

assertThat(response.getContentAsString()).isEqualTo("test");

}

@PathPatternsParameterizedTest
Expand Down

0 comments on commit a15f182

Please sign in to comment.