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

Using interactive-messages within lambda #896

Closed
5 of 15 tasks
dannyshaw opened this issue Oct 27, 2019 · 6 comments
Closed
5 of 15 tasks

Using interactive-messages within lambda #896

dannyshaw opened this issue Oct 27, 2019 · 6 comments
Labels
pkg:interactive-messages (deprecated) applies to `@slack/interactive-messages` question M-T: User needs support to use the project

Comments

@dannyshaw
Copy link

dannyshaw commented Oct 27, 2019

Description

I'm writing a serverless slack application and have been looking at using interactive-messages.
It seems quite tightly coupled with running a server.

dispatch() is marked as an internal method, however it seems like there should be a way for a serverless setup to manually pass a payload to the dispatcher.

Is this use case documented anywhere?

What type of issue is this? (place an x in one of the [ ])

  • bug
  • enhancement (feature request)
  • question
  • documentation related
  • testing related
  • discussion

Requirements (place an x in each of the [ ])

  • I've read and understood the Contributing guidelines and have done my best effort to follow them.
  • I've read and agree to the Code of Conduct.
  • I've searched for any related issues and avoided creating a duplicate issue.

Bug Report

Filling out the following details about bugs will help us solve your issue sooner.

Packages:

Select all that apply:

  • @slack/web-api
  • @slack/events-api
  • @slack/interactive-messages
  • @slack/rtm-api
  • @slack/webhooks
  • I don't know
@seratch
Copy link
Member

seratch commented Nov 2, 2019

Unfortunately, there is no documentation for the use case at the moment.

If your Lambda functions directly use the dispatch method, the functions must remember to do request signature verification like this before dispatching requests.

Considering the circumstances, creating an Express instance and converting it to a Lambda handler (we can use this npm modle by AWS or other options) may be simpler. Also, it makes testing the function on a local machine pretty easy.

@seratch seratch added the question M-T: User needs support to use the project label Nov 2, 2019
@aoberoi aoberoi added the pkg:interactive-messages (deprecated) applies to `@slack/interactive-messages` label Nov 14, 2019
@aoberoi
Copy link
Contributor

aoberoi commented Nov 14, 2019

The @slack/interactive-messages package exposes a standard node request listener.

You simply called the .requestListener() method on the adapter. You'll find an example in the documentation under the section for "Using an existing HTTP server".

I believe that for most serverless environments, you can implement the function the environment expects by calling the function you get from the method. This is essentially how the popular aws-serverless-express package works. In fact, there's likely some way to use that package to wrap the request listener returned by the adapter in this package, to make it compatible with AWS Lambda. i'm not an expert on this, but it would be great if you shared what you found!

@dannyshaw
Copy link
Author

Thanks all,

I managed to get around limitations using the requestListener, but I had to essentially write a mock Response object that @slack/interactive-mesages would call on as it is coupled to an http response object in the sendResponse() method

Here's the mock adaptor, I just instantiate it with the callback i'd like called when .end() is hit and the data being set by the sendResponse() is passed to that instead

// emulate a stripped down http response adapter for slack
class ResponseAdapter {
  constructor(callback) {
    this.callback = callback;
    this.headers = {};
    this._statusCode = 200;
  }

  set statusCode(val) {
    this._statusCode = val;
  }

  setHeader(key, val) {
    this.headers[key] = val;
  }
  end(content) {
    const data = {
      status: this._statusCode,
      json: content,
      headers: this.headers,
    };
    this.callback(data);
  }
}

and used something like this:

const handler = (req) {
  const interactions = createMessageAdapter(process.env.SIGNING_SECRET);  
  const listen = interactions.requestListener();

  // setup handlers
  interactions.action(
    /*...*/
  );

  const customResponseCreator = (status, json, headers) => {
    // create and process the response I actually need to send
  };

  const res = new ResponseAdapter(customResponseCreator);

  listen(req, res);

@aoberoi
Copy link
Contributor

aoberoi commented Nov 15, 2019

Whoa, that’s pretty neat. Thanks for sharing!

@kyle-johnson
Copy link

For others searching, you can directly use https://github.com/vendia/serverless-express if you include a middleware to populate rawBody:

const app = express();
app.use((req, res, next) => {
  // serverless-express populates `req.body` which makes interactive-messages error out unless
  // `req.rawBody` is populated.
  // As long as API Gateway is configured as a simple proxy to Lambda, the rawBody will be untouched
  // and interactive-messages will successfully verify signatures.
  if (req.body) {
    req.rawBody = req.body;
  }
  next();
});
app.use(createMessageAdapter(slackSigningSecret).requestListener());

// this app can now be used with serverless-express
export { app };

@dsuresh-ap
Copy link

Not sure if people are still having this issue but we had it with Azure functions. Turns out we needed to pass the content-type as application/json in the response. Hopefully that helps someone else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg:interactive-messages (deprecated) applies to `@slack/interactive-messages` question M-T: User needs support to use the project
Projects
None yet
Development

No branches or pull requests

5 participants