flask-openapi3
flask-openapi3 copied to clipboard
Support multi content type in request body and responses
Checklist:
- [x] Run
pytest testsand no failed. - [x] Run
ruff check flask_openapi3 tests examplesand no failed. - [x] Run
mypy flask_openapi3and no failed. - [x] Run
mkdocs serveand no failed.
Many people have multi content-type needs:
- #100
- #204
- #207
- #208
Here is a solution that can specify different content types for each class.
from flask import Request
from pydantic import BaseModel
from flask_openapi3 import OpenAPI
app = OpenAPI(__name__)
class DogBody(BaseModel):
a: int = None
b: str = None
model_config = {
"openapi_extra": {
"content_type": "application/vnd.dog+json"
}
}
class CatBody(BaseModel):
c: int = None
d: str = None
model_config = {
"openapi_extra": {
"content_type": "application/vnd.cat+json"
}
}
class BsonModel(BaseModel):
e: int = None
f: str = None
model_config = {
"openapi_extra": {
"content_type": "application/bson"
}
}
class ContentTypeModel(BaseModel):
model_config = {
"openapi_extra": {
"content_type": "text/csv"
}
}
@app.post("/a", responses={200: DogBody | CatBody | ContentTypeModel | BsonModel})
def index_a(body: DogBody | CatBody | ContentTypeModel | BsonModel):
"""
This may be confusing, if the content-type is application/json, the type of body will be auto parsed to
DogBody or CatBody, otherwise it cannot be parsed to ContentTypeModel or BsonModel.
The body is equivalent to the request variable in Flask, and you can use body.data, body.text, etc ...
"""
print(body)
if isinstance(body, Request):
if body.mimetype == "text/csv":
# processing csv data
...
elif body.mimetype == "application/bson":
# processing bson data
obj = BSON(body.data).decode()
new_body = body.model_validate(obj=obj)
print(new_body)
else:
# DogBody or CatBody
...
return {"hello": "world"}
if __name__ == '__main__':
app.run(debug=True)
As a result, some break changes had to be generated:
openapi_extrano longer supportsdescriptionandrequiredin request body, and instead usesrequest_body_descriptionandrequest_body_required.@app.post("/body", request_body_description="This is post RequestBody") def api_error_json(body: BookBody): ...openapi_extrano longer supportsdescription,headersandlinksin response, and replace with the following form.@app.get( "/test", responses={ "201": { "model": BaseResponse, "description": "Custom description", "headers": { "location": { "description": "URL of the new resource", "schema": {"type": "string"} } }, "links": { "dummy": { "description": "dummy link" } } } } ) def endpoint_test(): ...