Search code examples
node.jsslackhook.io

How to return both immediate and delayed response to slack slash command?


I'm trying to use a hook.io microservice to make a slack slash command bot. According to the docs I should be able to send an immediate response then a seperate POST later. But I cant get the immediate response and the later POST to both work.

Here is my test code.

module['exports'] = function testbot(hook) {

var request = require('request');
// The parameters passed in via the slash command POST request.
var params = hook.params;

data = {
    "response_type": "ephemeral",
    "text": "Immediate Response"
}
hook.res.setHeader('Content-Type', 'application/json');
console.log("returning immediate response")
hook.res.write(JSON.stringify(data), 'utf8', delay(params));
//calling end() here sends the immediate response but the POST never happens.
// but if end() is called below instead slack gives a timeout error but the POST succeeds.
//hook.res.end()

//test with 3.5 second delay
function delay(params) {
    setTimeout(function () {post_response(params)},3500);
}

function post_response(params) {

    console.log("posting delayed response")
    // Set up the options for the HTTP request.
    var options = {
        // Use the Webhook URL from the Slack Incoming Webhooks integration.
        uri: params.response_url,
        method: 'POST',
        // Slack expects a JSON payload with a "text" property.
        json: {"response_type":"in_channel", "text":"Delayed response","parse":"full"}
    };


    // Make the POST request to the Slack incoming webhook.
    request(options, function (error, response, body) {
        // Pass error back to client if request endpoint can't be reached.
        if (error) {
            console.log(error);
            hook.res.end(error.message);
        } else {
            console.log("post OK");
        }
        // calling end() here sends the POST but the immediate response is lost to a slack timeout error.
        hook.res.end()
    })
};
}

As detailed in the comments calling res.end() early means the immediate response gets sent but the POST never happens whereas delaying the res.end() until after POST means the delayed response is sent but it generates a timeout error from slack in the meantime.

I'm a javascript newbie so hopefully there is a simple solution that I've overlooked.


Solution

  • Once you call res.end() inside hook.io, the script will immediately abort and end processing. It's the equivalent of calling process.exit. If you fail to end the request, hook.io will eventually hit it's own Time-out Limit.

    hook.io should be capable of responding back to Slack within the three seconds Slack requires.

    Here is a guide which may help: Making a Custom Slack Slash Command with hook.io