HEAD mapping has higher priority over other conditions

When comparing multiple matching @RequestMapping's, the HTTP method
condition has the lowest precedence. It's mainly about ensuring an
explicit mapping wins over an implicit (i.e. no method) one.

As of 4.3 HTTP HEAD is handled automatically for controller methods
that match to GET. However an explicit mapping HTTP HEAD allows an
application to take control.

This commit ensures that for HTTP HEAD requests the HTTP method
condition is checked first which means that an explicit HEAD mapping
now trumps all other conditions.

Normally we look for the most specific matching @RequestMapping.
For HTTP HEAD we now look for the most specific match among
@RequestMapping methods with a HEAD mapping first.

Issue: SPR-14383
This commit is contained in:
Rossen Stoyanchev
2016-06-21 13:32:40 -04:00
parent db1092f119
commit 058279bc7e
2 changed files with 33 additions and 1 deletions

View File

@@ -34,6 +34,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.HEAD;
import static org.springframework.web.servlet.mvc.method.RequestMappingInfo.paths;
/**
@@ -171,6 +172,27 @@ public class RequestMappingInfoTests {
assertEquals(noMethods, list.get(2));
}
@Test // SPR-14383
public void compareToWithHttpHeadMapping() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("HEAD");
request.addHeader("Accept", "application/json");
RequestMappingInfo noMethods = paths().build();
RequestMappingInfo getMethod = paths().methods(GET).produces("application/json").build();
RequestMappingInfo headMethod = paths().methods(HEAD).build();
Comparator<RequestMappingInfo> comparator = (info, otherInfo) -> info.compareTo(otherInfo, request);
List<RequestMappingInfo> list = asList(noMethods, getMethod, headMethod);
Collections.shuffle(list);
Collections.sort(list, comparator);
assertEquals(headMethod, list.get(0));
assertEquals(getMethod, list.get(1));
assertEquals(noMethods, list.get(2));
}
@Test
public void equals() {
RequestMappingInfo info1 = paths("/foo").methods(GET)