使用 FastAPI 解析来自 Slack 的传入 POST 请求

问题描述 投票:0回答:1

我正在构建一个 FastAPI 服务器来接收 slacklash 命令发送的请求。使用下面的代码,我可以看到以下内容:

token=BLAHBLAH&team_id=BLAHBLAH&team_domain=myteam&channel_id=BLAHBLAH&channel_name=testme&user_id=BLAH&user_name=myname&command=%2Fwhatever&text=test&api_app_id=BLAHBLAH&is_enterprise_install=false&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%BLAHBLAH&trigger_id=BLAHBLAHBLAH

被打印出来,这正是我在官方文档中看到的有效负载。我正在尝试使用有效负载信息来做某事,我很好奇是否有一种解析此有效负载信息的好方法。我绝对可以使用 split 函数或任何其他漂亮的函数来解析这个有效负载,但我很好奇是否有一种“事实上的”方法来处理松弛有效负载。预先感谢!

from fastapi import FastAPI, Request

app = FastAPI()

@app.post("/")
async def root(request: Request):
    request_body = await request.body()
    print(request_body)
python slack fastapi slack-api slack-commands
1个回答
6
投票

接收
JSON
数据

您通常会使用 Pydantic 模型来声明请求主体 - 如果您要接收

JSON
形式的数据 - 从而受益于 Pydantic 必须提供的验证(有关如何发布的更多选项
JSON 
数据,看看这个答案)。因此,您可以定义这样的模型:

from pydantic import BaseModel

class Item(BaseModel):
    token: str
    team_id: str
    team_domain: str
    # etc.

@app.post("/")
def root(item: Item):
    print(item.dict())  # convert to dictionary (if required)
    return item

有效负载将如下所示:

{
    "token": "gIkuvaNzQIHg97ATvDxqgjtO"
    "team_id": "Foo",
    "team_domain": "bar",
    # etc.
}

接收
Form
数据

但是,如果您要接收作为

Form
数据 形式的有效负载,就像 slack API 所做的那样(如您提供的 link 中所示),您可以使用
Form
文件。使用
Form
字段,您的有效负载仍将根据这些字段以及您定义它们的类型进行验证。但是,您需要定义端点中的所有参数,如上面的链接所述并如下所示:

from fastapi import  Form

@app.post("/")
def root(token: str = Form(...), team_id: str = Form(...), team_domain: str = Form(...)):
    return {"token": token, "team_id": team_id, "team_domain": team_domain}

或者为了避免在端点中指定参数,如果您有大量

Form
字段,您可以创建一个 自定义依赖类(为简单起见,使用
@dataclass
装饰器),这将允许您可以在单独的类中定义多个
Form
字段,并且仅在端点中使用该类定义 - 有关 FastAPI 依赖项的更多详细信息,请参阅 这个答案这个答案。示例:

from dataclasses import dataclass
from fastapi import FastAPI, Form, Depends

@dataclass
class Item:
    token: str = Form(...)
    team_id: str = Form(...)
    team_domain: str = Form(...)
    #...

@app.post("/")
def root(data: Item = Depends()):
    return data

由于 FastAPI 实际上是 Starlette,即使您仍然必须按照问题中的方式访问请求正文,您也应该使用

request.json()
request.form()
等方法,如 Starlette 文档 中所述,这将允许您将请求正文分别解析为
JSON
form-data
。请查看此答案以获取更多详细信息和示例。

© www.soinside.com 2019 - 2024. All rights reserved.