如何以编程方式用主体实例化 Starlette 的请求?

Ale*_*lig 8 python starlette fastapi

我有一个包含一些使用 FastAPI 的 API 的项目,其中我需要调用项目内的 API 函数之一。使用 FastAPI 和 Starlette 的 API 函数如下所示

@router.put("/tab/{tab_name}", tags=["Tab CRUD"])
async def insert_tab(request: Request, tab_name: str):
    tab = await request.json()
    new_tab_name = tab["name"]
    new_tab_title = tab["title"]
    # Rest of the code
Run Code Online (Sandbox Code Playgroud)

我发送一个包含新选项卡数据的 JSON 作为我的请求正文,稍后将使用await request.json().

现在,我需要insert_tab在另一个函数中调用 ,因此我需要以某种方式实例化StarletteRequest中的对象。我之前已经这样做过,但没有 JSON 主体:

from starlette.requests import Request
from starlette.datastructures import Headers

headers = Headers()
scope = {
    'method': 'GET',
    'type': 'http',
    'headers': headers
}
request = Request(scope=scope)
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,我还需要将 JSON 主体注入到Request对象中,但我找不到一种方法来做到这一点。

有人以前做过这个或者知道我应该怎么做?

Tyl*_*ain 11

如果您尝试以编程方式从应用程序内调用另一个端点,最好跳过 HTTP 层并直接调用底层函数。

但是,如果您在尝试构建用于单元测试的模拟请求时进入此页面,请参阅以下示例:

from starlette.requests import Request
from starlette.datastructures import Headers


def build_request(
    method: str = "GET",
    server: str = "www.example.com",
    path: str = "/",
    headers: dict = None,
    body: str = None,
) -> Request:
    if headers is None:
        headers = {}
    request = Request(
        {
            "type": "http",
            "path": path,
            "headers": Headers(headers).raw,
            "http_version": "1.1",
            "method": method,
            "scheme": "https",
            "client": ("127.0.0.1", 8080),
            "server": (server, 443),
        }
    )
    if body:

        async def request_body():
            return body

        request.body = request_body
    return request
Run Code Online (Sandbox Code Playgroud)

有关使用 Starlette 的 ASGI 请求对象的更多信息,请访问:
https://www.encode.io/articles/working-with-http-requests-in-asgi