Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use request body with lazy listener when socket mode is enabled (v1.11.0) #552

Closed
JordanGibson opened this issue Dec 23, 2021 · 2 comments · Fixed by #555
Closed
Assignees
Labels
Milestone

Comments

@JordanGibson
Copy link

JordanGibson commented Dec 23, 2021

Reproducible in:

slack-bolt==1.11.0
slack-sdk==3.13.0
Python 3.8.8
ProductName: macOS
ProductVersion: 12.0
BuildVersion: 21A5506j
Darwin Kernel Version 21.1.0: Thu Aug 19 02:54:44 PDT 2021; root:xnu-8019.40.29~26/RELEASE_ARM64_T8101

The slack_bolt version

slack-bolt==1.11.0
slack-sdk==3.13.0

Python runtime version

Python 3.8.8

OS info

ProductName: macOS
ProductVersion: 12.0
BuildVersion: 21A5506j
Darwin Kernel Version 21.1.0: Thu Aug 19 02:54:44 PDT 2021; root:xnu-8019.40.29~26/RELEASE_ARM64_T8101

Steps to reproduce:

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

  1. Begin with the starter project for bolt-python in socket mode
  2. Enabling socket mode on the app
  3. Add functionality for FaaS (or at least, mock it) following the documentation
  4. Execute command /start-process sampletext

Expected result:

For the functions respond_to_slack_within_3_seconds and run_long_process to be called same with the body parameter for both calls.

Actual result:

The run_long_process body is empty ({}), and the respond_to_slack_within_3_seconds body is populated. This is evident as when I log the body on first execution of each call to both functions, the following is the output of the application (sensitive information redacted).

⚡️ Bolt app is running!
{'token': '***REDACTED***', 'team_id': '***REDACTED***', 'team_domain': '***REDACTED***', 'channel_id': '***REDACTED***', 'channel_name': '***REDACTED***', 'user_id': '***REDACTED***', 'user_name': '***REDACTED***', 'command': '/start-process', 'text': 'test', 'api_app_id': '***REDACTED***', 'is_enterprise_install': '***REDACTED***', 'response_url': ***REDACTED***', 'trigger_id': '***REDACTED***'}
{}
Failed to run an internal function ('text')

I do receive an Accepted response from respond_to_slack_within_3_seconds as it completes successfully, but I do not receive any messages from the run_long_process call as it fails to complete due to the body being empty.

For futher information, the respond parameter in run_long_process is assigned. For example, I removed the {body['text']} interpolation and it worked, sending the message Completed! (task: ) (task empty as I removed the replacement).

When in HTTP mode, it works fine (when changing the SocketModeHandler(app, ...).start() to app.start(.....))

app.py to reproduce

import os
import time

from slack_bolt import App

from slack_bolt.adapter.socket_mode import SocketModeHandler

app = App(token=os.environ.get("SLACK_BOT_TOKEN"), process_before_response=True)


def respond_to_slack_within_3_seconds(body, ack):
    text = body.get("text")
    if text is None or len(text) == 0:
        ack(":x: Usage: /start-process (description here)")
    else:
        ack(f"Accepted! (task: {body['text']})")


def run_long_process(respond, body):
    time.sleep(5)  # longer than 3 seconds
    respond(f"Completed! (task: {body['text']})")


app.command("/start-process")(
    ack=respond_to_slack_within_3_seconds,  # responsible for calling `ack()`
    lazy=[run_long_process]  # unable to call `ack()` / can have multiple functions
)

if __name__ == "__main__":
    SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
@JordanGibson
Copy link
Author

JordanGibson commented Dec 23, 2021

Update

After some investigation, I have been able to determine the root cause of this.

The culprit of this is how we create request objects when in socket mode (see slack_bolt/request/request.py:50). Currently, if the body is created as a dict instance, then we set the body to empty because we are unable to guarantee that order of the body will be perserved if we were to convert it to a str. As of Python 3.6+, dicts are ordered by insertion order.

@seratch
Copy link
Member

seratch commented Dec 24, 2021

Hi @JordanGibson, thanks for taking the time to report this issue!

I've checked this in detail and figured out the issue is a regression bug caused by #546 since v1.11.0 (the latest version). I will come up with a pull request to fix this and will release a patch version shortly.

seratch added a commit to seratch/bolt-python that referenced this issue Dec 24, 2021
seratch added a commit to seratch/bolt-python that referenced this issue Dec 24, 2021
seratch added a commit that referenced this issue Dec 24, 2021
@seratch seratch changed the title Unable to use request body with lazy listener when socket mode is enabled Unable to use request body with lazy listener when socket mode is enabled (v1.11.0) Mar 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants