我正在try 为一个FastAPI项目编写一个中间件,该项目在某些特殊情况下操作请求headers和/或query参数.

我已经设法捕获并修改了中间件中的请求对象,但似乎即使我修改了传递给中间件的请求对象,为端点提供服务的函数也会收到原始的、未修改的请求.

以下是我的实现的简化版本:

from fastapi import FastAPI, Request
from starlette.datastructures import MutableHeaders, QueryParams
from starlette.middleware.base import BaseHTTPMiddleware


class TestMiddleware(BaseHTTPMiddleware):


    def __init__(self, app: FastAPI):
        super().__init__(app)

    
    def get_modified_query_params(request: Request) -> QueryParams:

        pass  ## Create and return new query params


    async def dispatch(
        self, request: Request, call_next, *args, **kwargs
    ) -> None:
        
        # Check and manipulate the X-DEVICE-TOKEN if required
        header_key = "X-DEVICE-INFo"
        new_header_value = "new device info"

        new_header = MutableHeaders(request._headers)
        new_header[header_key] = new_header_value

        request._headers = new_header

        request._query_params = self.get_modified_query_params(request)

        print("modified headers  =>", request.headers)
        print("modified params  =>", request.query_params)

        return await call_next(request)

尽管我在上面的print语句中看到了更新的值,但当我try 在为端点提供服务的函数中打印请求对象时,我看到的是请求的原始值.

我遗漏了什么?

推荐答案

您需要更新request.scope['headers'],如this answer中所述.通过这种方式,您可以添加新的定制标头,也可以修改现有标头.以类似的方式,通过更新request.scope['query_string'],您可以修改现有的查询参数,也可以添加新的参数.

工作示例

from fastapi import FastAPI, Request
from urllib.parse import urlencode

app = FastAPI()

@app.middleware('http')
async def some_middleware(request: Request, call_next):
    # update request headers
    headers = dict(request.scope['headers'])
    headers[b'custom-header'] = b'my custom header'
    request.scope['headers'] = [(k, v) for k, v in headers.items()]
    
    # update request query parameters
    q_params = dict(request.query_params)
    q_params['custom-q-param'] = 'my custom query param'
    request.scope['query_string'] = urlencode(q_params).encode('utf-8')
        
    return await call_next(request)


@app.get('/')
async def main(request: Request):
    return {'headers': request.headers, 'q_params': request.query_params}

Python相关问答推荐

Pandas :多索引组

在Pandas 日历中插入一行

返回nxon矩阵的diag元素,而不使用for循环

将图像拖到另一个图像

PMMLPipeline._ fit()需要2到3个位置参数,但给出了4个位置参数

如何在python xsModel库中定义一个可选[December]字段,以产生受约束的SON模式

如何获得每个组的时间戳差异?

Pandas Loc Select 到NaN和值列表

在Python中使用if else或使用regex将二进制数据如111转换为001""

手动设置seborn/matplotlib散点图连续变量图例中显示的值

pysnmp—lextudio使用next()和getCmd()生成器导致TypeError:tuple对象不是迭代器''

从源代码显示不同的输出(机器学习)(Python)

什么是一种快速而优雅的方式来转换一个包含一串重复的列,而不对同一个值多次运行转换,

Python—在嵌套列表中添加相同索引的元素,然后计算平均值

使用np.fft.fft2和cv2.dft重现相位谱.为什么结果并不相似呢?

Scipy差分进化:如何传递矩阵作为参数进行优化?

Polars表达式无法访问中间列创建表达式

启动线程时,Python键盘模块冻结/不工作

在任何要保留的字段中添加引号的文件,就像在Pandas 中一样

如何在python tkinter中绑定键盘上的另一个回车?