required: false in POST body not honored? I think?
Description
---
openapi: "3.0.3"
info:
description: "Some service"
version: "0"
title: "hello"
contact:
email: "[email protected]"
servers:
- url: http://hello.com/1
paths:
/hello:
post:
summary: "hello"
description: "hello"
operationId: blah.endpoint
requestBody:
required: false
content:
application/json:
schema:
type: array
responses:
4XX:
description: "Failure"
200:
description: "Success"
Note the required: false property on the body clause. My understanding from the Swagger3 spec is that this indicates that the body can be omitted from the request. However, I get an error if I don't also include the x-nullable: true property. Shouldn't required: false be treated the same as x-nullable?
Specifically, I get:
http://127.0.0.1:8765/1/hello validation error: None is not of type 'array'
127.0.0.1 - - [05/Nov/2020 20:56:33] "POST /1/hello HTTP/1.1" 400 -
When I call it with this:
curl -v -X POST http://127.0.0.1:8765/1/hello
I get the same result with Python's requests.post with data=None.
I may be misunderstanding what curl and requests do with a null data value, but I think that means "no body supplied"?
I'm thinking is_null_value_valid should be set to True on the validator when required: false is provided.
Expected behaviour
That the endpoint func will be called with an empty body, since it is allowed by the Swagger definition, and that is what I'm passing.
Actual behaviour
400, and a nondescript error message that requires spelunking the code to understand
Steps to reproduce
See above
Additional info:
Output of the commands: Python 3.7.9 Version: 2.7.0
I get the same problem with type: object.
Thanks for the report @mmattb, I can indeed reproduce.
I quickly looked into the underlying issue, but it does not seem to be a quick fix. is_null_value_valid is indeed set to False when creating the RequestBodyValidator here:
https://github.com/zalando/connexion/blob/f45ef0e5aefbce100e0220dc698dd61768c654d3/connexion/operations/abstract.py#L435-L437
Unfortunately, it's not as easy as just changing the is_nullable function since the self.body_definition only contains the schema of the body, not the full definition with the required attribute.
You can work around this for now with x-nullable:
application/json:
schema:
type: array
x-nullable: true
Hi, I tried this workaround but I'm receiving another error:
{
"detail": "The browser (or proxy) sent a request that this server could not understand.",
"status": 400,
"title": "Bad Request",
"type": "about:blank"
}
This is the openapi spec that I've used:
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/InputBody'
components:
schemas:
InputBody:
type: object
x-nullable: true
properties:
tags:
type: array
items:
$ref: '#/components/schemas/TagInput'
Am I understanding this workaround incorrectly???
@20Aditya can you please post a minimal working example? Spec, python code and curl request.
Hi, here are the details:
Openapi Spec
openapi: "3.0.1"
info:
title: Store Service
description: "Store Service"
contact:
name: ""
version: 1.0.0
servers:
- url: http://127.0.0.1:9080/v1/
tags:
- name: Store
paths:
/store:
post:
tags:
- Store
summary: API Stores some data
requestBody:
content:
application/json:
schema:
x-nullable: true
$ref: '#/components/schemas/InputBody'
responses:
202:
description: Success
x-codegen-request-body-name: body
components:
schemas:
InputBody:
type: object
x-nullable: true
properties:
tags:
type: array
x-nullable: true
items:
$ref: '#/components/schemas/TagInput'
TagInput:
type: object
x-nullable: true
properties:
tagGroup:
type: string
example: "0010"
nullable: true
I'm using Openapi code-generator to generate the api code using cli:
java -cp openapi-generator-cli-4.0.0.jar org.openapitools.codegen.OpenAPIGenerator generate -i openapi.yaml -g python-flask -o ' + OUT_DIR --model-package model
Note the x-nullable: true flag that I've given in the component schemas under type: object
When I hit the endpoint with this curl request:
curl -X POST 'localhost:9080/v1/store' -H 'Content-Type: application/json'
I get the error that I've described above:
{
"detail": "The browser (or proxy) sent a request that this server could not understand.",
"status": 400,
"title": "Bad Request",
"type": "about:blank"
}
Versions
"Flask==1.1.2",
"connexion==2.0.0",
"waitress==1.3.0",
"Werkzeug==0.16.0",
"swagger-ui-bundle==0.0.2",
"python_dateutil==2.6.0",
"openapi_spec_validator==0.2.9",
"jsonschema==2.6.0",
Please let me know if any further information is required.
I am seeing very similar behavior w/ Connexion 2.13.0 and POST requests with required: false bodies. I couldn't make it work with x-nullable: true and my behavior is slightly different. Even if the body is in fact null/none, Connexion seems to be getting an empty string and responds with:
code=400, description="Bad request: '' is not of type 'object'."
I am using Connexion with aiohttp, fwiw. Minimal example here https://github.com/rschmied/conex
Verification:
pip install connexion==2.11.2POST with empty body --> workspip install connexion==2.13.0POST with empty body -->'' is not of type 'object'.
First is with 2.11.2, second with 2.13.0:
$ curl -X POST http://localhost:8080/api/hello
{"result": "empty"}
$ curl -X POST http://localhost:8080/api/hello
{"type": "about:blank", "title": "Bad Request", "detail": "'' is not of type 'object'", "status": 400}
$