如何添加任意标头以使用FastAPI进行响应


在FastAPI中,必须添加响应标头以进行漏洞对策。

我想为每个响应添加相同的标头,但 FastAPI文档没有提及它(找到),最初是我不知道的路径操作功能(例如@app.post("/comment")装饰器)如何仅通过每个设置进行整体设置)。
这次我要介绍的主要内容是如何将其添加到所有响应中,但是由于在这里这很重要,因此我将以交叉方式介绍这两种方法。

在下面的示例中,我们假设返回图像的API设置为Cache-Control
当然,可以用相同的方式设置Content-Security-PolicyX-Frame-Options

1.如何添加到路径操作功能

这是官方Fast API文档中的方法。

如下所示,将类型为Response的类添加到路径操作函数的参数。

1
2
3
4
5
6
7
from fastapi import Response

@app.get("/image")
def image(response: Response)
    response.headers["Cache-Control"] = "no-cache, no-store"
    ...
    return image_instance

这样,原来是这样的响应,

response_before.png

您可以看到已添加"缓存控件"。

response_after.png

2.如何添加到所有资源

您可以使用本文档中描述的方法。

1
2
3
4
5
@app.middleware("http")
async def add_my_headers(request: Request, call_next):
    response = await call_next(request)
    response.headers["Cache-Control"] = "no-cache, no-store"
    return response

通过更改

response.headers键可以设置多个标题。

也可以使用FastAPI依赖的名为Starlette的库的类BaseHTTPMiddleware进行编写。

1
2
3
4
5
6
7
from starlette.middleware.base import BaseHTTPMiddleware

class MyHeadersMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        response = await call_next(request)
        response.headers["Cache-Control"] = "no-cache, no-store"
        return response

在这种情况下,设置上面为main.py等中定义的FastAPI实例创建的类。

1
2
3
app = FastAPI()

app.add_middleware(MyHeadersMiddleware)

顺便说一下,对于CORS,准备了专用的CORSMiddleware,它支持通过正则表达式进行白名单,因此最好不使用上述实现就使用它。
您可以在FastAPI教程中阅读有关此内容的更多信息。 (fastapi.middleware.cors.CORSMiddleware类实际上只是starlette.middleware.cors.CORSMiddleware的别名。)

小心错误处理

当引发

异常或通过Pydantic验证处理错误时,即使在方法2出现错误的情况下,也可以毫无问题地添加标头,但方法1不会输出设置的标头。

当然,即使使用方法1,如果直接在FastAPI的官方文档中所示的路径操作函数中处理错误处理,也可以毫无问题地输出。

1
2
3
4
    if error:
        return JSONResponse(
            {}, status_code=404, headers={"Cache-Control": "no-cache, no-store"}
        )

但是,如果对所有错误情况都进行处理,则存在处理遗漏的风险,因此在许多情况下,您可能必须定义并处理@app.exception_handler。我认为如果在这种情况下为每个路径操作函数编写处理会很复杂,因此在许多情况下,采用方法2而不是方法1并根据响应的内容和错误的内容重写标头。我认为最好将它提供给您。

概要

到目前为止,我已经介绍了两种向FastAPI响应添加任意HTTP标头的方法。

FastAPI在业务中使用很困难,因此我希望将来能写一些系列文章。