[wp-trac] [WordPress Trac] #46191: REST API parameter validation should handle multiple error messages/codes. (was: WP_REST_Request::has_valid_params() should utilize get_error_messages() and not get_error_message(). Unexpected behavior occurs when you try to WP_Error->add() in the REST API)
WordPress Trac
noreply at wordpress.org
Mon Feb 1 23:00:38 UTC 2021
#46191: REST API parameter validation should handle multiple error messages/codes.
--------------------------------------+-----------------------
Reporter: tmfespresso | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: 5.8
Component: REST API | Version: 4.4
Severity: normal | Resolution:
Keywords: has-patch has-unit-tests | Focuses: rest-api
--------------------------------------+-----------------------
Changes (by TimothyBlynJacobs):
* milestone: 5.7 => 5.8
Comment:
Thanks for testing @xkon! I'm reiterating some of our conversation on
Slack to note it for posterity. And this sort of turned into a stream of
consciousness, so apologies in advance :D.
Yeah so one of the issues is that error data is attached to the error
code, not the `code` and `message` together thru `add()`. Disambiguating
this is I think essentially impossible because even if we did somehow make
changes to `add` to keep track of this, a user can just call `add_data` at
anytime.
I was thinking we might be able to only include data for the first time an
error code appears. So for example:
{{{
{
"code": "rest_invalid_param",
"message": "Invalid parameter(s): id",
"data": {
"status": 400,
"params": {
"id": "This is our first error. Well this is yet another error :D."
}
},
"additional_errors": [
{
"code": "rest_test_error",
"message": "This is our first error.",
"data": {
"param": "id"
},
"param": "id",
"additional_data": [
{
"status": 420
},
{
"status": 410
}
]
},
{
"code": "rest_test_error",
"message": "Well this is yet another error :D.",
"param": "id"
}
]
}
}}}
This, however, would be a breaking change. We would have to instead only
omit the `additional_data`, and keep the `data` around.
{{{
{
"code": "rest_invalid_param",
"message": "Invalid parameter(s): id",
"data": {
"status": 400,
"params": {
"id": "This is our first error. Well this is yet another error :D."
}
},
"additional_errors": [
{
"code": "rest_test_error",
"message": "This is our first error.",
"data": {
"param": "id"
},
"param": "id",
"additional_data": [
{
"status": 420
},
{
"status": 410
}
]
},
{
"code": "rest_test_error",
"message": "Well this is yet another error :D.",
"data": {
"param": "id"
},
"param": "id"
}
]
}
}}}
This reduces the response size. But may make it harder for clients that
need to operate on the error data more complicated. However, I suppose any
operation on that would be wrong since they wouldn't be able to use the
right data.
I'm not sure what the correct move is here. If I could see anyway to
actually track error data to a code/message, I'd punt until we could
figure that out. But I'm really not sure what that would look like.
For example, imagine two `enum` parameters `enum_a` and `enum_b`. If we
wanted to get the `enum` for each, we'd run into an issue disambiguating.
{{{
{
"code": "rest_invalid_param",
"message": "Invalid parameter(s): enum_a, enum_b",
"data": {
"status": 400,
"params": {
"enum_a": "enum_a is not one of a, b, c.",
"enum_b": "enum_b is not one of d, e, f."
}
},
"additional_errors": [
{
"code": "rest_not_in_enum",
"message": "enum_a is not one of a, b, c.",
"data": {
"param": "enum_a"
},
"param": "enum_a",
"additional_data": [
{
"enum": ["a", "b", "c"]
},
{
"enum": ["d", "e", "f"]
}
]
},
{
"code": "rest_not_in_enum",
"message": "enum_b is not one of d, e, f.",
"data": {
"param": "enum_b"
},
"param": "enum_b",
"additional_data": [
{
"enum": ["a", "b", "c"]
},
{
"enum": ["d", "e", "f"]
}
]
}
]
}
}}}
Thinking on it more, it would actually be worse since the same thing would
happen to the `param` data.
{{{
{
"code": "rest_invalid_param",
"message": "Invalid parameter(s): enum_a, enum_b",
"data": {
"status": 400,
"params": {
"enum_a": "enum_a is not one of a, b, c.",
"enum_b": "enum_b is not one of d, e, f."
}
},
"additional_errors": [
{
"code": "rest_not_in_enum",
"message": "enum_a is not one of a, b, c.",
"data": {
"param": "enum_a"
},
"param": "enum_a",
"additional_data": [
{
"param": "enum_b"
},
{
"enum": ["a", "b", "c"]
},
{
"enum": ["d", "e", "f"]
}
]
},
{
"code": "rest_not_in_enum",
"message": "enum_b is not one of d, e, f.",
"data": {
"param": "enum_a"
},
"param": "enum_a",
"additional_data": [
{
"param": "enum_b"
},
{
"enum": ["a", "b", "c"]
},
{
"enum": ["d", "e", "f"]
}
]
}
]
}
}}}
I wonder if @dlh or @johnbillion have any thoughts on this. It feels like
an inescapable problem that data isn't attached to a `code` ''and''
`message`.
Given all that, I'm going to punt this. I'm not certain what the right
solution is, or if there is one, but this definitely needs improvement.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/46191#comment:10>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list