如何在FastAPI中的中间件中更新/修改请求头和查询参数?

huangapple go评论65阅读模式
英文:

How to update/modify request headers and query parameters in a FastAPI middleware?

问题

I'm trying to write a middleware for a FastAPI project that manipulates the request headers and / or query parameters in some special cases.

I've managed to capture and modify the request object in the middleware, but it seems that even if I modify the request object that is passed to the middleware, the function that serves the endpoint receives the original, unmodified request.

Here is a simplified version of my implementation:

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)

Even though I see the updated values in the print statements above, when I try to print request object in the function that serves the endpoint, I see original values of the request.

What am I missing?

英文:

I'm trying to write a middleware for a FastAPI project that manipulates the request headers and / or query parameters in some special cases.

I've managed to capture and modify the request object in the middleware, but it seems that even if I modify the request object that is passed to the middleware, the function that serves the endpoint receives the original, unmodified request.

Here is a simplified version of my implementation:

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)

Even though I see the updated values in the print statements above, when I try to print request object in the function that serves the endpoint, I see original values of the request.

What am I missing?

答案1

得分: 2

以下是翻译好的部分:

要更新或修改请求的头部(headers),您需要更新request.scope['headers'],如此答案所描述的那样。通过这种方式,您可以添加新的自定义头部,以及修改现有的头部。类似地,通过更新request.scope['query_string'],您可以修改现有的查询参数(query parameters),以及添加新的参数。下面是一个工作示例。

工作示例

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

app = FastAPI()

@app.middleware('http')
async def some_middleware(request: Request, call_next):
    # 更新请求头部
    headers = dict(request.scope['headers'])
    headers[b'custom-header'] = b'my custom header'
    request.scope['headers'] = [(k, v) for k, v in headers.items()]
    
    # 更新请求查询参数
    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}
英文:

To update or modify the request headers, you would need to update request.scope['headers'], as described in this answer. In that way, you could add new custom headers, as well as modify existing ones. In a similar way, by updating request.scope['query_string'], you could modify existing query parameters, as well as add new ones. A working example is given below.

Working Example

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}

huangapple
  • 本文由 发表于 2023年5月17日 11:17:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76268348.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定