FastAPI 默认会使用 JSONResponse 返回响应。
你可以通过直接返回 Response 来重载它,参见 直接返回响应。
但如果你直接返回 Response,返回数据不会自动转换,也不会自动生成文档(例如,在 HTTP 头 Content-Type 中包含特定的「媒体类型」作为生成的 OpenAPI 的一部分)。
你还可以在 路径操作装饰器 中声明你想用的 Response。
你从 路径操作函数 中返回的内容将被放在该 Response 中。
并且如果该 Response 有一个 JSON 媒体类型(application/json),比如使用 JSONResponse 或者 UJSONResponse 的时候,返回的数据将使用你在路径操作装饰器中声明的任何 Pydantic 的 response_model 自动转换(和过滤)。
说明
如果你使用不带有任何媒体类型的响应类,FastAPI 认为你的响应没有任何内容,所以不会在生成的OpenAPI文档中记录响应格式。
例如,如果你需要压榨性能,你可以安装并使用 orjson 并将响应设置为 ORJSONResponse。
导入你想要使用的 Response 类(子类)然后在 路径操作装饰器 中声明它。
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
app = FastAPI()
@app.get("/items/", response_class=ORJSONResponse)
async def read_items():
return [{"item_id": "Foo"}]
提示
参数 response_class 也会用来定义响应的「媒体类型」。
在这个例子中,HTTP 头的 Content-Type 会被设置成 application/json。
并且在 OpenAPI 文档中也会这样记录。
小贴士
ORJSONResponse 目前只在 FastAPI 中可用,而在 Starlette 中不可用。
使用 HTMLResponse 来从 FastAPI 中直接返回一个 HTML 响应。
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/items/", response_class=HTMLResponse)
async def read_items():
return """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
提示
参数 response_class 也会用来定义响应的「媒体类型」。
在这个例子中,HTTP 头的 Content-Type 会被设置成 text/html。
并且在 OpenAPI 文档中也会这样记录。
正如你在 直接返回响应中了解到的,你也可以通过直接返回响应在 路径操作 中直接重载响应。
和上面一样的例子,返回一个 HTMLResponse 看起来可能是这样:
from fastapi import FastAPI
from fastapi.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)
警告
路径操作函数 直接返回的 Response 不会被 OpenAPI 的文档记录(比如,Content-Type 不会被文档记录),并且在自动化交互文档中也是不可见的。
提示
当然,实际的 Content-Type 头,状态码等等,将来自于你返回的 Response 对象。
如果你想要在函数内重载响应,但是同时在 OpenAPI 中文档化「媒体类型」,你可以使用 response_class 参数并返回一个 Response 对象。
接着 response_class 参数只会被用来文档化 OpenAPI 的 路径操作,你的 Response 用来返回响应。
比如像这样:
from fastapi import FastAPI
from fastapi.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/", response_class=HTMLResponse)
async def read_items():
return generate_html_response()
在这个例子中,函数 generate_html_response() 已经生成并返回 Response 对象而不是在 str 中返回 HTML。
通过返回函数 generate_html_response() 的调用结果,你已经返回一个重载 FastAPI 默认行为的 Response 对象,
但如果你在 response_class 中也传入了 HTMLResponse,FastAPI 会知道如何在 OpenAPI 和交互式文档中使用 text/html 将其文档化为 HTML。
这里有一些可用的响应。
要记得你可以使用 Response 来返回任何其他东西,甚至创建一个自定义的子类。
技术细节
你也可以使用 from starlette.responses import HTMLResponse。
FastAPI 提供了同 fastapi.responses 相同的 starlette.responses 只是为了方便开发者。但大多数可用的响应都直接来自 Starlette。
其他全部的响应都继承自主类 Response。
你可以直接返回它。
Response 类接受如下参数:
FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它还将包含一个基于 media_type 的 Content-Type 头,并为文本类型附加一个字符集。
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/legacy/")
def get_legacy_data():
data = """<?xml version="1.0"?>
<shampoo>
<Header>
Apply shampoo here.
</Header>
<Body>
You'll have to use soap here.
</Body>
</shampoo>
"""
return Response(content=data, media_type="application/xml")
如上文所述,接受文本或字节并返回 HTML 响应。
接受文本或字节并返回纯文本响应。
from fastapi import FastAPI
from fastapi.responses import PlainTextResponse
app = FastAPI()
@app.get("/", response_class=PlainTextResponse)
async def main():
return "Hello World"
接受数据并返回一个 application/json 编码的响应。
如上文所述,这是 FastAPI 中使用的默认响应。
如上文所述,ORJSONResponse 是一个使用 orjson 的快速的可选 JSON 响应。
UJSONResponse 是一个使用 ujson 的可选 JSON 响应。
警告
在处理某些边缘情况时,ujson 不如 Python 的内置实现那么谨慎。
from fastapi import FastAPI
from fastapi.responses import UJSONResponse
app = FastAPI()
@app.get("/items/", response_class=UJSONResponse)
async def read_items():
return [{"item_id": "Foo"}]
小贴士
ORJSONResponse 可能是一个更快的选择。
返回 HTTP 重定向。默认情况下使用 307 状态代码(临时重定向)。
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/typer")
async def redirect_typer():
return RedirectResponse("https://typer.tiangolo.com")
采用异步生成器或普通生成器/迭代器,然后流式传输响应主体。
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
async def fake_video_streamer():
for i in range(10):
yield b"some fake video bytes"
@app.get("/")
async def main():
return StreamingResponse(fake_video_streamer())
如果您有类似文件的对象(例如,由 open() 返回的对象),则可以在 StreamingResponse 中将其返回。
包括许多与云存储,视频处理等交互的库。
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
some_file_path = "large-video-file.mp4"
app = FastAPI()
@app.get("/")
def main():
def iterfile(): # (1)
with open(some_file_path, mode="rb") as file_like: # (2)
yield from file_like # (3)
return StreamingResponse(iterfile(), media_type="video/mp4")
小贴士
注意在这里,因为我们使用的是不支持 async 和 await 的标准 open(),我们使用普通的 def 声明了路径操作。
异步传输文件作为响应。
与其他响应类型相比,接受不同的参数集进行实例化:
文件响应将包含适当的 Content-Length,Last-Modified 和 ETag 的响应头。
from fastapi import FastAPI
from fastapi.responses import FileResponse
some_file_path = "large-video-file.mp4"
app = FastAPI()
@app.get("/")
async def main():
return FileResponse(some_file_path)
您还可以使用 response 在 OpenAPI 中声明媒体类型和许多其他详细信息:OpenAPI 中的额外文档。