Build a Chat App with Stream & Kong

Managing microservices manually can get very complicated and takes the focus away from business logic. API gateways help take care of the various collective management and housekeeping tasks necessary for running microservices.

One of the most popular API gateways is Kong. As the illustration below shows, Kong takes care of the tedious tasks involved in managing and running microservices while leaving you to focus on building exciting features by leveraging on products like Stream Chat for live chats or Stream Activity Feeds for creating engaging activity feeds.

In this tutorial, we will be creating a live chat app using Stream Chat and a backend microservice exposed through Kong's API gateway.

Prerequisites

Before you proceed with this tutorial, make sure you have Docker, Node.js, and npm or yarn installed on your machine. We'll be building the frontend with Svelte and the backend with Express. Both are chosen because of their simplicity and so that you can understand and follow along even if this is your first encounter with them. Being minimalist tools, they don't distract from what's going on.

Sign up for Stream Chat

Visit this link to create a free Stream account or login to your existing account. Once you’re logged in, go to your dashboard, hit the blue “Create App” button at the top right of the screen and give your app a name as shown below:

In the App Access Keys section at the bottom, copy your Key and Secret for use later.

Kong Setup

We'll be setting up Kong using Docker to keep our local machine clean and free of dependencies, and using Docker ensures that the steps are the same for all platforms.

We need to create a Docker network for Kong and our microservices, then setup Kong's database where its configurations will be stored, and start-up Kong after that.

https://gist.github.com/ukchukx/801b24a527475e5b84bb24c7ad8c89ed

You can verify that Kong is running with:

$ curl -i http://localhost:8001/

For Kong to know about our microservice, we need to configure the microservice and tell Kong how to route requests to our app. But, we first have to create the microservice.

Setting up the Chat Microservice

Let's create our folder structure, initialize the project, and install the needed dependencies:

https://gist.github.com/ukchukx/a8933d22b3efbabef9f787d6e182c317

After that, create a file called index.js in the backend directory and paste in the code below:

https://gist.github.com/ukchukx/d5cb795db7672c0aad246d13becec677

We have two routes. The /token endpoint accepts a username and generates a new token using the Stream Chat Node.js SDK, as we need to authenticate any new users before they can gain access. The /ping endpoint is to check if the server is running.

Create a .env file in the current directory (backend) and add your key and secret you copied from your Stream dashboard:

https://gist.github.com/ukchukx/e3030c3c283b55c532749183163923a8

In the scripts section of package.json in the backend directory, add a start command to run the server as shown below:

https://gist.github.com/ukchukx/654c25573ca3ee6449feb367c2ba2797

Start the server with:

$ npm start

Now that we've successfully written our backend microservice let's Dockerize it so Kong can manage it.

Add a Dockerfile in the backend directory and paste in:

https://gist.github.com/ukchukx/d9c34e9eacae8ed952e0d51198bff181

Then, in the root directory (kongchat) add a docker-compose.yml file and paste in:

https://gist.github.com/ukchukx/c0a639283f3a38cdce7dc39d74e39e56

With this, we can run our backend service using:

$ docker-compose up -d

Or, if you prefer it to run in the foreground:

$ docker-compose up

Registering Our Microservice With Kong

Now our back-end microservice is up and running; we need to tell Kong about it. To do so, we need to know its IP address on the kong-net network. We can find that out by running:

https://gist.github.com/ukchukx/3cb94f9caa756513e73f87f67867fc65

My microservice IP address, for example, is 172.19.0.4, as seen from the IPv4Address key of the Containers field. I omitted the irrelevant parts of the output.

Now we have our IP address in hand; we register it with Kong by making a POST request to Kong's services endpoint:

https://gist.github.com/ukchukx/81dbe1bcced84f4e5eee204d589f665a

Now Kong knows about our microservice. We then need to tell Kong what requests to route to our microservice:

https://gist.github.com/ukchukx/e5fcbbe137b1118da8e8a2f23b4d6c28

With that, we just told Kong to route GET and POST requests made to /api/kongchat to our microservice.

We can check that Kong is correctly routing our API requests to our microservice by sending a request to /ping:

https://gist.github.com/ukchukx/5179e53ad12ff3a2490094cfb07e0299

Since we'll be communicating with Kong from the browser, we need to turn on the CORS plugin for our service:

https://gist.github.com/ukchukx/b1a93758a73ca6ce67387e04c489d6e5

Creating Our Frontend

In the frontend directory, we created earlier, run:

https://gist.github.com/ukchukx/e4b5119b86985fad8a6abd72d6316b94

We're using Tailwind CSS for our styling. So let's integrate it into our development pipeline.
In postcss.config.js, paste in:

https://gist.github.com/ukchukx/551b60bf30c45909a34c41295b050920

Replace the contents of rollup.config.js with:

https://gist.github.com/ukchukx/53b00d2665a8121c715d6addb38da1ac

Our changes complete the setup of our CSS pre-processing and inject our environment variables for use in the app.

Modify the style tag of App.svelte as below:

https://gist.github.com/ukchukx/ee34e4007a5ef30cb16d85e6f7ad10f5

That's all for our CSS pre-processing. Let's dive into the mechanism of connecting to our proxied microservice.

When a user first loads the app, we want to show the login page below:

When the user types a username and clicks on Sign in, we want to show the chat window like the example below:

The contents of our App.svelte is shown below:

https://gist.github.com/ukchukx/a276fa1ab3c77025db979aeebba719a6

Let's go through the code.

At the beginning of our component's template, we have the app name and an indicator that shows if our microservice is up and running:

https://gist.github.com/nparsons08/c455409d8e75eeb79f3f6b71a8237dec

We call the /ping endpoint we created on the microservice using pingService() at intervals determined by pingInterval.

When the user first opens the app (s)he is not logged in (loggedIn is false) so we show the login form:

https://gist.github.com/nparsons08/3e7e13b1fd93f790f575ef8d052d2c73

Submitting the login form will call joinChat() which sends a request to the Kong gateway to get a token. When the token is returned, we initialize Stream Chat (initializeStreamChat()) and our messaging channel (initializeChannel()), then we set loggedIn to true, retrieve previous messages (if any) and register a listener for new messages to the channel.
We then show the chat window for logged in users:

https://gist.github.com/nparsons08/a4528615b40c22b8a6ac2739e6a3386f

When the Send button is clicked, we publish the contents of message to the channel and empty it after that, and Stream Chat ensures that all registered clients get the newly published message.

Demo

Open the app in different browser windows, log in with different usernames, and you can send messages between the logged-in users as shown in the images below:

Conclusion

You can find out more about Stream Chat and Kong by going through their documentation. The source code for this tutorial is hosted on GitHub.

TutorialsChat