Paul Gerhartz Paul Gerhartz - 3 months ago 28
HTTP Question

Express: Post Request handler doesn't stop calling a function

My express app should call a function once, but it repeatedly calls it an infinite number of times when handling a POST request. I can't figure out why it's called more than once.

This app works with Slack Events API and receives an event from Slack as a post request when a message is posted to a specific Slack channel. Once the app receives the event, it responds with a 200-status response to alert Slack it received it. Then the app extracts the text property from the request and calls postMessage with the text to post the message to a different channel. Posting the message to a different channel won't kick off another event.

The problem is that postMessage() gets called infinitely until I manually crash the app

Here I setup the app and wait for post requests:

const express = require('express');
var bodyParser = require('body-parser');

var app = express();
var jsonParser = bodyParser.json();

// Wait for post requests, then extract it's text
app.post('/', jsonParser, function (req, res) {
if (!req.body){
return res.sendStatus(400);
} else {
postMessage(req.body.event.text); //Should be called once
}

// Respond to Slack Event API we received their request
res.writeHead(200, {'Content-Type': 'application/json'});
res.end();
});
}

app.listen(config('PORT'), (err) => {
if (err) throw err
console.log(`App LIVES on PORT ${config('PORT')}`);
});


The body of the request is structured like:

body = {
event: {
text: "important message"
}
}


The function that keeps getting called. This will post a message to a Slack channel:

function postMessage(message){
var messagePath = 'https://slack.com/api/chat.postMessage?token=xxx&message=' + message;
request(messagePath, function(error, response, body){
if (!error && response.statusCode == 200){
console.log('message sent successfully');
} else {
console.log('error == ' + error);
}
});
}


The postMessage method does get called with the correct text. The problem is that it's called more than once.

I thought Slack's API was possibly sending the same request multiple times but from their documentation they will wait 3 seconds between sending requests. My app will call postMessage() about a hundred times in a second, so I don't think it's being overloaded with requests from Slack

Thank you in advance!

Answer

My guess is that your bot, which is listening to posted messages and then responding to those messages, is responding to itself when it posts. This will lead to an infinite loop.

The fix is to write a check to make sure the bot is not responding to itself. Inspect req.body.event and see if a username is being sent with each message. Then you can write something like this:

app.post('/', jsonParser, function (req, res) {
    if (!req.body || !req.body.event){
        return res.sendStatus(400);
    } else if (req.body.event.user_name !== '<OUR_USER_NAME>') { // Make sure we are not responding to ourselves
        postMessage(req.body.event.text); // Should be called once
    }

    // Respond to Slack Event API we received their request
    res.writeHead(200, {'Content-Type': 'application/json'});
    res.end();
});