mirror of https://github.com/tiangolo/fastapi.git
📝 Add docs for custom response
This commit is contained in:
parent
0df2720490
commit
f6667ecfb0
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
|
|
@ -0,0 +1,115 @@
|
||||||
|
!!! warning
|
||||||
|
This is a rather advanced topic.
|
||||||
|
|
||||||
|
If you are starting with **FastAPI**, you might not need this.
|
||||||
|
|
||||||
|
By default, **FastAPI** will return the responses using Starlette's `JSONResponse`.
|
||||||
|
|
||||||
|
But you can override it.
|
||||||
|
|
||||||
|
## Use `UJSONResponse`
|
||||||
|
|
||||||
|
For example, if you are squeezing performance, you can use `ujson` and set the response to be Starlette's `UJSONResponse`.
|
||||||
|
|
||||||
|
### Import `UJSONResponse`
|
||||||
|
|
||||||
|
```Python hl_lines="2"
|
||||||
|
{!./tutorial/src/custom-response/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Notice that you import it directly from `starlette.responses`, not from `fastapi`.
|
||||||
|
|
||||||
|
### Make your path operation use it
|
||||||
|
|
||||||
|
Make your path operation use `UJSONResponse` as the response class using the parameter `content_type`:
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!./tutorial/src/custom-response/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
The parameter is called `content_type` because it will also be used to define the "media type" of the response.
|
||||||
|
|
||||||
|
And will be documented as such in OpenAPI.
|
||||||
|
|
||||||
|
## HTML Response
|
||||||
|
|
||||||
|
To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
|
||||||
|
|
||||||
|
### Import `HTMLResponse`
|
||||||
|
|
||||||
|
```Python hl_lines="2"
|
||||||
|
{!./tutorial/src/custom-response/tutorial002.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Notice that you import it directly from `starlette.responses`, not from `fastapi`.
|
||||||
|
|
||||||
|
|
||||||
|
### Define your `content_type` class
|
||||||
|
|
||||||
|
Pass `HTMLResponse` as the parameter `content_type` of your path operation:
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!./tutorial/src/custom-response/tutorial002.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
The parameter is called `content_type` because it will also be used to define the "media type" of the response.
|
||||||
|
|
||||||
|
In this case, the HTTP header `Content-Type` will be set to `text/html`.
|
||||||
|
|
||||||
|
And it will be documented as such in OpenAPI.
|
||||||
|
|
||||||
|
|
||||||
|
### return a Starlette `Response`
|
||||||
|
|
||||||
|
You can also override the response directly in your path operation.
|
||||||
|
|
||||||
|
If you return an object that is an instance of Starlette's `Response`, it will be used as the response directly.
|
||||||
|
|
||||||
|
The same example from above, returning an `HTMLResponse`, could look like:
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!./tutorial/src/custom-response/tutorial003.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
Of course, the `Content-Type` header will come from the the `Response` object your returned.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
A `Response` returned directly by your path operation function won't be documented in OpenAPI and won't be visible in the automatic interactive docs.
|
||||||
|
|
||||||
|
|
||||||
|
### Document in OpenAPI and override `Response`
|
||||||
|
|
||||||
|
If you want to override the response from inside of the function but at the same time document the "media type" in OpenAPI, you can use the `content_type` parameter AND return a `Response` object.
|
||||||
|
|
||||||
|
The `content_type` class will then be used only to document the OpenAPI path operation, but your `Response` will be used as is.
|
||||||
|
|
||||||
|
#### Return an `HTMLResponse` directly
|
||||||
|
|
||||||
|
For example, it could be something like:
|
||||||
|
|
||||||
|
```Python hl_lines="7 23"
|
||||||
|
{!./tutorial/src/custom-response/tutorial004.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the function `generate_html_response()` already generates a Starlette `Response` instead of the HTML in a `str`.
|
||||||
|
|
||||||
|
By returning the result of calling `generate_html_response()`, you are already returning a `Response` that will override the default **FastAPI** behavior.
|
||||||
|
|
||||||
|
#### Declare `HTMLResponse` as `content_type`
|
||||||
|
|
||||||
|
But by declaring it also in the path operation decorator:
|
||||||
|
|
||||||
|
```Python hl_lines="21"
|
||||||
|
{!./tutorial/src/custom-response/tutorial004.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### OpenAPI knows how to document it
|
||||||
|
|
||||||
|
...**FastAPI** will be able to document it in OpenAPI and in the interactive docs as HTML with `text/html`:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/custom-response/image01.png">
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from starlette.responses import UJSONResponse
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/", content_type=UJSONResponse)
|
||||||
|
async def read_items():
|
||||||
|
return [{"item_id": "Foo"}]
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from starlette.responses import HTMLResponse
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/", content_type=HTMLResponse)
|
||||||
|
async def read_items():
|
||||||
|
return """
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Some HTML in here</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Look ma! HTML!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from starlette.responses import HTMLResponse
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/")
|
||||||
|
async def read_items():
|
||||||
|
html_content = """
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Some HTML in here</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Look ma! HTML!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
return HTMLResponse(content=html_content, status_code=200)
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from starlette.responses import HTMLResponse
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
def generate_html_response():
|
||||||
|
html_content = """
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Some HTML in here</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Look ma! HTML!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
return HTMLResponse(content=html_content, status_code=200)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/", content_type=HTMLResponse)
|
||||||
|
async def read_items():
|
||||||
|
return generate_html_response()
|
||||||
|
|
@ -36,6 +36,7 @@ nav:
|
||||||
- Request Forms and Files: 'tutorial/request-forms-and-files.md'
|
- Request Forms and Files: 'tutorial/request-forms-and-files.md'
|
||||||
- Path Operation Configuration: 'tutorial/path-operation-configuration.md'
|
- Path Operation Configuration: 'tutorial/path-operation-configuration.md'
|
||||||
- Path Operation Advanced Configuration: 'tutorial/path-operation-advanced-configuration.md'
|
- Path Operation Advanced Configuration: 'tutorial/path-operation-advanced-configuration.md'
|
||||||
|
- Custom Response: 'tutorial/custom-response.md'
|
||||||
- Concurrency and async / await: 'async.md'
|
- Concurrency and async / await: 'async.md'
|
||||||
- Deployment: 'deployment.md'
|
- Deployment: 'deployment.md'
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue