Skip to content

Commit

Permalink
Support multiple media types under the same status code
Browse files Browse the repository at this point in the history
  • Loading branch information
iongion committed Nov 29, 2024
1 parent 4f031b7 commit 41334c3
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 7 deletions.
32 changes: 32 additions & 0 deletions docs/Example.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,38 @@ if __name__ == '__main__':
app.run(debug=True)
```

## Multiple media types

```python

@app.get(
'/book/<int:bid>',
tags=[book_tag],
summary='new summary',
description='new description',
responses={
200: {
"description": "Multiple media types under the same status code",
"content": {
"application/json": BookResponse,
"application/xml": BookResponse,
}
},
201: {"content": {"text/csv": {"schema": {"type": "string"}}}}
},
security=security
)
def get_book(path: BookPath):
"""Get a book
to get some book by id, like:
http://localhost:5000/book/3
"""
if path.bid == 4:
return NotFoundResponse().dict(), 404
return {"code": 0, "message": "ok", "data": {"bid": path.bid, "age": 3, "author": 'no'}}

```

## APIBlueprint

```python
Expand Down
40 changes: 33 additions & 7 deletions flask_openapi3/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,13 +328,44 @@ def get_responses(
_responses = {}
_schemas = {}

def register_schema(name, schema: Any) -> None:
_schemas[name] = Schema(**schema)
definitions = schema.get("$defs")
if definitions:
# Add schema definitions to _schemas
for name, value in definitions.items():
_schemas[normalize_name(name)] = Schema(**value)

for key, response in responses.items():
if response is None:
# If the response is None, it means HTTP status code "204" (No Content)
_responses[key] = Response(description=HTTP_STATUS.get(key, ""))
elif isinstance(response, dict):
response["description"] = response.get("description", HTTP_STATUS.get(key, ""))
_responses[key] = Response(**response)
if "content" in response:
response_content_map = {}
for content_type, model in response["content"].items():
if isinstance(model, dict):
# inline schema
response_content_map[content_type] = MediaType(
schema=Schema(**model["schema"])
) if "schema" in model else MediaType(
schema=Schema(type=DataType.STRING)
)
elif issubclass(model, BaseModel):
# pydantic model
schema = get_model_schema(model, mode="serialization")
original_title = schema.get("title") or model.__name__
name = normalize_name(original_title)
response_content_map[content_type] = MediaType(
schema=Schema(**{"$ref": f"{OPENAPI3_REF_PREFIX}/{name}"})
)
register_schema(name, schema)
_responses[key] = Response(
description=HTTP_STATUS.get(key, ""),
content=response_content_map)
else:
_responses[key] = Response(**response)
else:
# OpenAPI 3 support ^[a-zA-Z0-9\.\-_]+$ so we should normalize __name__
schema = get_model_schema(response, mode="serialization")
Expand Down Expand Up @@ -367,12 +398,7 @@ def get_responses(
_content["application/json"].encoding = openapi_extra.get("encoding") # type: ignore
_content.update(openapi_extra.get("content", {})) # type: ignore

_schemas[name] = Schema(**schema)
definitions = schema.get("$defs")
if definitions:
# Add schema definitions to _schemas
for name, value in definitions.items():
_schemas[normalize_name(name)] = Schema(**value)
register_schema(name, schema)

components_schemas.update(**_schemas)
operation.responses = _responses
Expand Down

0 comments on commit 41334c3

Please sign in to comment.