Spring 5.3.8

@PostMapping("/foo/bar")
void doSomething(){..}

@GetMapping("/foo/{id}")
Foo getFoo(@PathVariable Long id) {..}

For

OPTIONS /foo/bar

PartialMatchHelper will return both mappings, but it should only return the PostMapping.

Comment From: happyWilliam0

@Ickbinet Hi, I think it's not a bug, 1.When I followed the issue, the problem did not appear.In fact it will only return one method by HttpMethod. 2.Even if the HttpMethod of the two methods is consistent, a higher match will be returned after sorting. 3.PartialMatchHelper is used to print partial matching infromation when there is no matching.

Comment From: Ickbinet

Hm... which spring version do you use? I tested with 2.5.6.

I got:

$ curl -i -X OPTIONS localhost:8081/foo/bar HTTP/1.1 200 Allow: POST,GET,HEAD,OPTIONS Accept-Patch: Content-Length: 0 Date: Tue, 09 Nov 2021 11:22:48 GMT

Comment From: happyWilliam0

I tested with 5.2.x and 5.3.x.

Comment From: Ickbinet

Hm, ok, plain Spring, I used Spring Boot 2.5.6

Comment From: Ickbinet

What is the required setup to test it without Boot? war-deployment Tomcat V x.y?

Comment From: bclozel

In case of no match for an incoming request, the PartialMatchHelper will look at the request and try to loosely find a method that could have matched and throw an informative error - this happens in the RequestMappingInfoHandlerMapping.

As explained in the Javadoc there, we're trying to get all the matching patterns and then consider: * method mismatch * produce/consume mismatch * params mismatch

In this case, OPTIONS /foo/bar matches both "/foo/bar" and "/foo/{id}" patterns, but the latter would fail for params. Note that if the @PostMapping handler in your sample would have a request body parameter (which is quite common for POST requests), the argument you're making would also apply there and the POST method should not match.

In summary, the PartialMatchHelper is a best effort mechanism and is trying to catch common mistakes. Right now I don't see a way to consistently honor the behavior you're describing without breaking many, common use cases.

I'm closing this as it is working as designed.