-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
POST with no body calls RPC function with json argument; crashes #2399
Comments
According to the docs, |
I don't disagree, but do note even with the current behaviour you won't be "guaranteed" to call that function since the query will crash before the function is invoked! The current behaviour might be semantically correct but practically useless at the same time. I think if we want to keep the "always use single parameter JSON function when I give this header, even when I don't send a payload" behaviour then it would make sense to either:
In our case at least the second option would work nicely. And again it's not the end of the world if the current behaviour is left as is. I want to emphasise I posted this issue more to highlight the change in behaviour and help others who stumble onto it. It might be considered unexpected and an undocumented change in behaviour (even if the previous behaviour was indeed unintentional). |
Ah, well, PostgREST does call the function under the hood, with an empty string parameter: Now, doing the same test with GET does not throw the error and treats empty params (in the query string) as an empty object, we could use a similar logic here and say that an empty body (empty raw string) means we should use an empty json object as you suggested. All in all, I like both of your suggestions. I prefer the second one, but maybe the error message is less opinionated (could be argued that an empty array instead of empty object is also valid). I'll tag it as Just to leave a note of what I found while reviewing this. When doing this request: POST /rpc/hello
Content-Type: application/json
Prefer: params=single-object
[
{"a": 1},
{"b": 1}
] It returns the "All object keys must match" error, which means it's parsing the body here: postgrest/src/PostgREST/Request/ApiRequest.hs Lines 385 to 387 in 35a114a
I don't think the body should be parsed for the |
I would consider this a bug. The |
Regarding /rpc/func?id=arg.3&name=arg.nom Following that idea and with underscore operators, we could avoid the special POST /rpc/func?myjson=_arg.*
{..}
Right now what we have for POST is basically a: POST /rpc/func?id=_arg.id&name=_arg.name
{"id": 1, "name": "nom"} |
I misunderstood I'd still consider this a bug, but would expect the function to be called with an empty object instead of without argument when this header is passed. Edit: This is exactly what happens on a |
Hm. There seem to be a few more inconsistencies with CREATE OR REPLACE FUNCTION test.hello(_payload json) RETURNS jsonb LANGUAGE SQL AS $$ select $1::JSON $$;
CREATE OR REPLACE FUNCTION test.hello() RETURNS jsonb LANGUAGE SQL AS $$ select '"no payload"'::JSON $$; The following happens: expected results
unexpected results
Basically, when using
Interestingly, the situation is a bit different when turning the function into one with an unnamed json parameter: CREATE OR REPLACE FUNCTION test.hello(json) RETURNS jsonb LANGUAGE SQL AS $$ select $1::JSON $$;
CREATE OR REPLACE FUNCTION test.hello() RETURNS jsonb LANGUAGE SQL AS $$ select '"no payload"'::JSON $$; This basically allows to call the functions in the same way as with the named parameter, when using expected results
unexpected results
While this seems to be exactly what @aljungberg tried to achieve - I don't understand why we try to parse the json body at all, when passing it on to a "single unnamed json parameter function". I would expect everything to just go through and the no argument function to be never called except in the last case. |
@wolfgangwalther Yeah, the json shouldn't be parsed in that case. Likely it was done that way to reuse some code. |
Environment
Description of issue
We have an overloaded RPC method, something like this:
Note there's one version which takes no argument.
Previously, Postgrest would call the second one if a request didn't have a body. After upgrading, it now instead tries to use the first one which predictably crashes because the empty string is not valid JSON ("invalid input syntax for type json").
I'm not sure what changed but I imagine it's to do with #1735 somehow. We do send the
Prefer "params=single-object"
header, and if we don't the no-arg RPC function becomes callable again. The argument version on the other hand stops being callable.Discussion
I guess it's debatable whether this is a bug or not. The
Prefer "params=single-object"
header does indicate we want to send a JSON object, so sending the header with an empty body is poorly defined.I can't see any harm in restoring the old behaviour should you choose to do so. Passing an empty string as JSON will never work, so when the
Content-Type
is json (or not set), and theContent-Length
is 0, it makes sense to always select the parameter-less version of an RPC function.For us, the header is added in the nginx proxy automatically (to support some legacy clients). So the fix was simply to not send that header when the content-length is 0. Still, I'm posting this issue in case it might help others and to highlight it is an undocumented backwards incompatible change.
The text was updated successfully, but these errors were encountered: