slackapi / bolt-python

A framework to build Slack apps using Python
https://tools.slack.dev/bolt-python/
MIT License
1.06k stars 245 forks source link

Handling url encoded action request from slack in slack bolt #846

Closed 0x108 closed 1 year ago

0x108 commented 1 year ago

Greetings, I am using the Python edition of the Slack bolt adapter. I am experiencing an issue, where if I receive an action from slack, the request body sent by Slack looks scrambled, e.g. like this:

b'payload=%7B%22type%22%3A%22block_actions%22%2C%22user%22%3A%7B%22id%22%3A%22XXXX%22%2C%22username%22%3A%22XXXX%22%2C%22name%22%3A%22XXXXX%22%2C%22team_id%22%3A%22XXXXX%22%7D%2C%22a

If I however receive a message event, everything is fine and in the expected JSON format.:

b'{"token":"XXXX","team_id":"XXXX","enterprise_id":"XXXX","context_team_id":null,"context_enterprise_id":"XXXX","api_app_id":"XXXX","event":{"client_msg_id"...

I am using the code provided here: https://github.com/slackapi/bolt-python/blob/main/examples/fastapi/async_app.py

Let me know if I can provide more details, Happy about hearing from you and thanks in advance!

The slack_bolt version

1.16.3

Python runtime version

3.11.2

OS info

ProductName: macOS ProductVersion: 13.0.1 BuildVersion: 22A400 Darwin Kernel Version 22.1.0: Sun Oct 9 20:15:09 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T6000

Steps to reproduce:

(Share the commands to run, source code, and project settings (e.g., setup.py))

  1. Click any button in slack from the bot
  2. Bot server receives request
  3. Bot receives payload in wrong format
  4. Bot server answers with 404 not found

Expected result:

Normally the @app.action decorator should trigger the handling function

Actual result:

I receive an error 404: "POST /slack/events HTTP/1.1" 404 Not Found

seratch commented 1 year ago

Hi @0x108, thanks for asking the question!

I know that the difference of the formats can be quite confusing but it's what it is. And bolt-python handles the difference for you under the hood. So, it is not an issue at all. If you have some kind of additional middleware in the FastAPI app, those may change the behavior for the action data request patterns. But this is just my guess. I am still not sure the reason why your app does not work.

Just in case, I've verified the async app built with FastAPI works without any issues on my end (plus many developers across the world have been using the adapter for years). Here is a simple app I used for the test. I hope this may help.

import logging

logging.basicConfig(level=logging.DEBUG)

from slack_bolt.async_app import AsyncApp
from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler

app = AsyncApp()
app_handler = AsyncSlackRequestHandler(app)

@app.event("app_mention")
async def handle_app_mentions(say):
    await say(
        text="You can add a button alongside text in your message.",
        blocks=[
            {
                "type": "section",
                "block_id": "b",
                "text": {
                    "type": "mrkdwn",
                    "text": "You can add a button alongside text in your message. ",
                },
                "accessory": {
                    "type": "button",
                    "action_id": "a",
                    "text": {"type": "plain_text", "text": "Button"},
                    "value": "click_me_123",
                },
            }
        ]
    )

@app.event("message")
async def handle_message():
    pass

@app.action("a")
async def handle_some_action(ack, respond):
    await ack()
    await respond("Hey!")

from fastapi import FastAPI, Request

api = FastAPI()

@api.post("/slack/events")
async def endpoint(req: Request):
    return await app_handler.handle(req)
0x108 commented 1 year ago

Thank you very much for the detailed response! - I realised after trying your code snippet in the exact way, that I didn't handle the app.action correctly.

My desired code should look like this, as it should handle all actions:

@app.action(re.compile(".*"))

My handling of messages, which also handles all messages using @app.message("") has caused some confusion for me, in regards why it wouldn't work for @app.action("")

Thank you for helping me out & have a great day!