slackapi / bolt-js

A framework to build Slack apps using JavaScript
https://tools.slack.dev/bolt-js/
MIT License
2.75k stars 394 forks source link

A new receiver: HTTPReceiver (eventually the default) #670

Closed aoberoi closed 3 years ago

aoberoi commented 4 years ago

The problem

Currently, Bolt ships with one implementation of the Receiver interface called ExpressReceiver. It works great for lots of developers, but there are some issues we've heard about:

Our current recommendation for developers facing the issues above is to implement their own Receiver. But that comes with new issues:

Lastly, developers want access to more context from the HTTP requests and response. However, Bolt was built to support Receivers that do not interface directly with HTTP. For example, it should be possible to built a LambdaReceiver that doesn't use an HTTP server at all, which receives data from a function call. Another example is a TestReceiver which also doesn't start an HTTP server, and receives data loaded from fixtures from test scenarios. This list goes on. App developers should expect that they can swap one receiver for another and their app to continue working. Therefore adding context from HTTP in the current state, without a a larger plan, would allow and encourage developers to write more coupled, less reusable, code. This would undermine the potential future value of a vibrant ecosystem of shared code (receivers, middleware, etc).

Our solution

We will build a more generalized HTTPReceiver that has no dependency on express.

The HTTPReceiver will have its own built in server (just like ExpressReceiver) that can be .start()ed easily. But alternatively the receiver can be used as a listener for the request event - a common low-level interface that can easily be used with most existing web frameworks.

The goal is nobody should want to write another HTTP-specific receiver because this one is flexible enough to work for everyone's needs. If we achieve this goal, the issues derived from copying and pasting the code from the ExpressReceiver are also solved.

We will also generalize the OAuth implementation so that it can easily be started as part of the HTTPReceiver or without it. We have not yet designed what an API for what this might look like. It could be an object which has its own built-in HTTP server that can be started, or be used as a request listener. In the worst case, OAuth is supported in the HTTPReceiver, but when using any other receiver developers need to use the @slack/oauth API directly.

The ReceiverEvent interface will be extended to carry receiver-specific data, such as HTTP headers, AWS Lambda context, test scenario data, etc. The exact shape of the change has not been decided yet. Although extending the interface with receiver-specific data can lead to tightly coupled code and later a fragmented ecosystem, we believe by generalizing the receiver to the point where nobody would want to implement another HTTP one sufficiently mitigates the risk of too many similar receivers putting similar data (like HTTP headers) in different places in different formats. We'd like to make the separation between the Slack data and the receiver-specific context very obvious, and discourage people from using the latter in reusable code.

Lastly, we will start working on this change soon. It might be released in a 2.x minor release, but it will surely arrive by 3.0. And on 3.0, we'd like to make HTTPReceiver the default.

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

aoberoi commented 4 years ago

These are the parts we'd still like to discuss, and nail down before implementation begins:

seratch commented 3 years ago

759 looks related to the part:

The ReceiverEvent interface will be extended to carry receiver-specific data, such as HTTP headers, AWS Lambda context, test scenario data, etc. The exact shape of the change has not been decided yet.

@aoberoi @stevengill Do you already have design ideas for this in your mind?

stevengill commented 3 years ago

@seratch the plan was to break that out of this issue into its own issue and do it after the 3.0 release. I think we can safely use #759 as the issue now.