Enviroment
I use OpenJDK 8 + Spring Boot + Gradle + GNU/Linux.
What is the problem?
When parsing the UUID from a parameter you can have a NumberFormatException
if the user send a malformed id, like as 11111111-1111-1111-1111-111111111111x
. By example:
@GetMapping("/{id}")
public String test(@PathVariable("id") UUID id) {
The Spring says:
org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.util.UUID'; nested exception is java.lang.NumberFormatException: For input string: "111111111111x"
Same problem with any non string type, like as Integer, i need use a regex validation for each mapping, like as:
@GetMapping("/{id:\d+}")
public String test(@PathVariable("id") Integer id) {
Or using UUID:
@GetMapping("/{id:^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$}")
public String test(@PathVariable("id") UUID id) {
What should be the proper execution?
Spring should not return uncontrollable errors directly, this can cause problems if the programmer does not perform all the proper checks on a layer above the controller.
If the controller requires a numeric type value as a parameter, then it should not be executed in the mapping, if the type casting fails then the function should not be executed and it should continue searching for the next controller.
I understand that the mapping is done at setup time and not run time, but this causes uncontrolled and unsolicited values to hit the controller.
Another possible solution is that when configuring the application (from Spring) and generating the route map, you should consider the @PathVariable
type annotations and obtain the object type of the variable and apply a native filtering as an expression regular, in this way if my controller requires a value of type Integer
, it should not be executed if a non-numeric String
type data comes.
It would be a good idea for Spring to avoid incorrect type mapping instead of throwing an exception of type MethodArgumentTypeMismatchException
.
Comment From: quaff
It make sense.
Comment From: durm
Up
It looks like a proper solution is to return 400 bad request with message about type mismatch
Comment From: bclozel
Sorry it took us so long to process this issue.
This exception is raised by the method argument resolver mechanism, and this is the expected behavior. We have dedicated tests for this, see RequestHeaderMethodArgumentResolverTests
.
If the controller requires a numeric type value as a parameter, then it should not be executed in the mapping, if the type casting fails then the function should not be executed and it should continue searching for the next controller.
The handled is never executed and controllers can contribute exception handlers for this.
I understand that the mapping is done at setup time and not run time, but this causes uncontrolled and unsolicited values to hit the controller.
The mapping is done at runtime. With the proposed change, a request with an invalid value would not cause an exception, but a 404: if an invalid value is given, then other controller handlers are considered and most likely a "catch-all" handler for static resources will handle it, resulting in a 404. I don't think this would be an improvement here.
I'm closing this issue as a result.
Comment From: vstoykov
@bclozel
Recently I hit the same problem and I need to add few more cents to the issue.
From the HTTP specs point of view let's imagine we have the following resource: https://example.com/users/123e4567-e89b-12d3-a456-426655440000
If client make a GET request as follows:
GET https://example.com/users/123e4567
This is effectively missing resource which should result in 404 instead of 400. Response 400 is generally raised when there is an error in the body or some header of the request and not when the PATH is non existent.
The main confusion here comes from the fact that MethodArgumentTypeMismatchException
is raised no matter if the method argument is mapped to the path, the body or some header. As mentioned the semantic from HTTP point of view is different depending on where the error is.
The proposal mentioned from the author of the issue is to threat path variables differently then headers, and body.
I understand that debugging such an issue of incorrect mapping from the developer will be more hard if the response is 404 instead of 400 with description what is the issue, but from HTTP point of view is the correct solution.