0

I'm building a fastapi server to receive request sent by slack slash command. Using the code below, I could see that 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 was printed, which is exactly the payload I saw in official doc(https://api.slack.com/interactivity/slash-commands#app_command_handling). I'm trying to use the payload information to do something, and I'm curious whether there's a great way of parsing this payload info. I can definitely parse this payload using split function or any other beautiful functions, but I'm curious whether there is a 'de facto' way of dealing with slack payload. Thanks in advance!

from fastapi import FastAPI, Request

app = FastAPI()


@app.post("/")
async def root(request: Request):
    request_body = await request.body()
    print(request_body)
Piljae Chae
  • 797
  • 6
  • 13

1 Answers1

2

You would normally use Pydantic models to declare a request body - if you were about to receive data in JSON form - thus benefiting from the validation that Pydantic has to offer. So, you would define a model like this:

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

The payload would look like this:

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

If, however, you were about to receive the payload as Form data, just like what slack API does (as shown in the link you provided), you could use Form fileds. With Form fields, your payload will still be validated against those fields and the type you define them with. You would need, however, to define all the parameters in the endpoint, as described in the above link and as shown below:

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}

or to avoid that, you may want to have a look at this, which describes how to use Pydantic models with Form fields.

As FastAPI is actually Starlette underneath, even if you still had to access the request body in the way you show in the question, you should rather use methods such as request.json() or request.form(), as described in Starlette documentation, which allow you to get the request body parsed as JSON or form-data, respectively.

Chris
  • 4,940
  • 2
  • 7
  • 28