Skip to content
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

openapi: remove JSON body second validation and type casting #1170

Merged
merged 3 commits into from
Apr 27, 2022

Conversation

p4l1ly
Copy link
Contributor

@p4l1ly p4l1ly commented Mar 4, 2020

JSON body is already validated using jsonschema. There was also some type
casting but it was wrong: e.g. not recurring deeply into dicts and lists,
relying on existence of "type" in schema (which is not true e.g. if
oneOf is used). Anyway, the only reason why types should be casted is
converting integer values to float if the type is number. But this is in
most cases irrelevant.

Added an example, which did not work before this commit (echoed {})
e.g. for

curl localhost:8080/api/foo -H 'content-type: application/json' -d '{"foo": 1}'

but now the example works (echoes {"foo": 1}).

Fixes #691

Changes proposed in this pull request:

From OpenAPIOperation._get_body_argument:

  • remove additional validation which is already done via jsonschema (including additionalProperties handling)
  • remove type casting which didn't work either and it is irrelevant as the specification says that the number type is for both integers and floats so we don't need to forcibly convert int to float (and there's really nothing else to convert in the json-parsed body).

@p4l1ly
Copy link
Contributor Author

p4l1ly commented Mar 4, 2020

I forgot to mention that there was also some not-fully-working default value handling (which worked only for top-most entity). I've removed that too. Currently, the only working default value handling in body is AFAIK using this approach and if using aiohttp, also this fix (which has unfortunately not yet been merged) is needed.

@p4l1ly
Copy link
Contributor Author

p4l1ly commented Mar 4, 2020

ok, removing the default value handling breaks tests. I was not thinking about form bodies etc.

@coveralls
Copy link

coveralls commented Mar 4, 2020

Coverage Status

Coverage increased (+0.01%) to 96.3% when pulling b70cdac on p4l1ly:oneof into 96bdcb0 on zalando:master.

@p4l1ly p4l1ly changed the title openapi: remove body preprocessing openapi: remove JSON body preprocessing Mar 4, 2020
@p4l1ly p4l1ly changed the title openapi: remove JSON body preprocessing openapi: remove JSON body second validation and type casting Mar 4, 2020
@p4l1ly
Copy link
Contributor Author

p4l1ly commented Mar 4, 2020

To increase coverage, I have removed some edge case checking, for the edge cases that I could not achieve in tests. Could you please check it?

@dtkav
Copy link
Collaborator

dtkav commented Mar 11, 2020

You might find #1140 interesting. I was doing similar work, but haven't had any free time to finish it up.

@p4l1ly
Copy link
Contributor Author

p4l1ly commented Mar 13, 2020

I've found #1140 interesting, but it covers quite a big part of the connexion's code and I'm afraid I will not find time to dive into it in a foreseeable future. I'm not sure if #1140 makes handling of JSON bodies correct, maybe I could transform the example in this pull request into test so that it could be added into #1140?

@RobbeSneyders
Copy link
Member

Hi @p4l1ly
Happy to review if you can rebase on and retarget to the v2 branch. We can later cherry pick it to main for v3.

@p4l1ly p4l1ly force-pushed the oneof branch 2 times, most recently from 474ee55 to 8fe35a3 Compare April 9, 2022 11:23
@p4l1ly p4l1ly changed the base branch from master to v2 April 9, 2022 11:26
@p4l1ly p4l1ly force-pushed the oneof branch 2 times, most recently from 534707b to e70f6e5 Compare April 11, 2022 12:10
Body is already validated using jsonschema. There was also some type
casting but it was wrong: e.g. not recurring deeply into dicts and lists,
relying on existence of "type" in schema (which is not there e.g. if
oneOf is used). Anyway, the only reason why types should be casted is
converting integer values to float if the type is number. But this is in
most cases irrelevant.

Added an example, which did not work before this commit (echoed `{}`)
e.g. for
```
curl localhost:8080/api/foo -H 'content-type: application/json' -d
'{"foo": 1}'
```
but now the example works (echoes `{"foo": 1}`).
@p4l1ly
Copy link
Contributor Author

p4l1ly commented Apr 11, 2022

Hi @RobbeSneyders , thanks for your response. I've rebased, retargeted and slightly refactored the pull request.

@RobbeSneyders RobbeSneyders self-requested a review April 14, 2022 07:11
Copy link
Member

@RobbeSneyders RobbeSneyders left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @p4l1ly

Could you convert the example into a test?


if x_body_name in arguments or has_kwargs:
return {x_body_name: res}
return self._get_typed_body_values(body_arg, body_props, additional_props)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this for form types and not json?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because for json, strings are already converted to appropriate python types via json.loads. But there's no such conversion for forms, only string splitting of arrays. So I have left forms to be processed the old way and focused on fixing json, which is simpler to fix and more important (oneOf is rare in form data).

In my opinion, proper solution would perform type conversions somehow via jsonschema validators, at one place, close to the start of the request handling pipeline. Currently, types are converted inconsistently here and there and there and there. But please, this was intended to be a quick simple bugfix MR, let's not dive into big refactorings here.

@p4l1ly
Copy link
Contributor Author

p4l1ly commented Apr 26, 2022

@RobbeSneyders, I've just converted the example into a test.

Copy link
Member

@RobbeSneyders RobbeSneyders left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @p4l1ly.

@Ruwann I suggest to release this as 2.14.0 since we no longer cast numbers to float.

@RobbeSneyders RobbeSneyders merged commit 792bc4d into spec-first:v2 Apr 27, 2022
@Ruwann
Copy link
Member

Ruwann commented May 4, 2022

Thanks for the efforts!

Indeed, let's release as 2.14.0 :)

RobbeSneyders added a commit that referenced this pull request May 4, 2022
* Fix uri parsing for query parameter with empty brackets (#1501)

* Update tests for changed werkzeug behavior in 2.1 (#1506)

pallets/werkzeug#2352

* Bugfix/async security check (#1512)

* Add failing tests

* Use for else construct

* openapi: remove JSON body second validation and type casting (#1170)

* openapi: remove body preprocessing

Body is already validated using jsonschema. There was also some type
casting but it was wrong: e.g. not recurring deeply into dicts and lists,
relying on existence of "type" in schema (which is not there e.g. if
oneOf is used). Anyway, the only reason why types should be casted is
converting integer values to float if the type is number. But this is in
most cases irrelevant.

Added an example, which did not work before this commit (echoed `{}`)
e.g. for
```
curl localhost:8080/api/foo -H 'content-type: application/json' -d
'{"foo": 1}'
```
but now the example works (echoes `{"foo": 1}`).

* test with oneOf in the requestBody

* remove oneof examples: superseded by tests

Co-authored-by: Pavol Vargovcik <pavol.vargovcik@kiwi.com>

Co-authored-by: Ruwann <ruwanlambrichts@gmail.com>
Co-authored-by: Pavol Vargovčík <pavol.vargovcik@gmail.com>
Co-authored-by: Pavol Vargovcik <pavol.vargovcik@kiwi.com>
gaetano-guerriero pushed a commit to athenianco/especifico that referenced this pull request Aug 11, 2022
…rst#1170)

* openapi: remove body preprocessing

Body is already validated using jsonschema. There was also some type
casting but it was wrong: e.g. not recurring deeply into dicts and lists,
relying on existence of "type" in schema (which is not there e.g. if
oneOf is used). Anyway, the only reason why types should be casted is
converting integer values to float if the type is number. But this is in
most cases irrelevant.

Added an example, which did not work before this commit (echoed `{}`)
e.g. for
```
curl localhost:8080/api/foo -H 'content-type: application/json' -d
'{"foo": 1}'
```
but now the example works (echoes `{"foo": 1}`).

* test with oneOf in the requestBody

* remove oneof examples: superseded by tests

Co-authored-by: Pavol Vargovcik <pavol.vargovcik@kiwi.com>
gaetano-guerriero pushed a commit to athenianco/especifico that referenced this pull request Aug 11, 2022
…rst#1170)

* openapi: remove body preprocessing

Body is already validated using jsonschema. There was also some type
casting but it was wrong: e.g. not recurring deeply into dicts and lists,
relying on existence of "type" in schema (which is not there e.g. if
oneOf is used). Anyway, the only reason why types should be casted is
converting integer values to float if the type is number. But this is in
most cases irrelevant.

Added an example, which did not work before this commit (echoed `{}`)
e.g. for
```
curl localhost:8080/api/foo -H 'content-type: application/json' -d
'{"foo": 1}'
```
but now the example works (echoes `{"foo": 1}`).

* test with oneOf in the requestBody

* remove oneof examples: superseded by tests

Co-authored-by: Pavol Vargovcik <pavol.vargovcik@kiwi.com>
vmarkovtsev added a commit to athenianco/especifico that referenced this pull request Aug 12, 2022
…operties

openapi: remove JSON body second validation and type casting (spec-first#1170)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

oneOf does not work on requestBody when oneOf is nested under #/components/schemas
5 participants