Amazon AWS

Publishing & Subscribing to AWS SNS Messages with Node.js

Hello. In this tutorial, we will see publishing and subscribing to AWS SNS Messages with Node.js. We will understand AWS SNS and create a simple application that will interact with SNS with the help of exposed endpoints.

1. Introduction

AWS Simple Notification Service (SNS) is a cloud service for delivering notifications from applications to subscribed endpoints and clients. It is a service that enables to send notifications on a specific topic to its consumers (i.e. receivers) through various communication channels like SNS, Email, HTTP, HTTPS, AWS, SQS, Lambda.

  • Supports over 200+ countries for SNS and Email notifications
  • Guarantees message delivery as long as SMS or Email address is valid
  • Provides excellent and well-written SDK

1.1 Setting up Node.js

To set up Node.js on windows you will need to download the installer from this link. Click on the installer (also include the NPM package manager) for your platform and run the installer to start with the Node.js setup wizard. Follow the wizard steps and click on Finish when it is done. If everything goes well you can navigate to the command prompt to verify if the installation was successful as shown in Fig. 1.

aws sns publish - Verifying node and npm installation
Fig. 1: Verifying node and npm installation

2. Publishing and Subscribing to AWS SNS Messages with Node.js

To set up the application, we will need to navigate to a path where our project will reside. For programming stuff, I am using Visual Studio Code as my preferred IDE. You’re free to choose the IDE of your choice.

2.1 Application pre-requisite(s)

To successfully implement this tutorial we will need –

  • AWS CLI user who should have an SNS full access policy attached to it so that it can successfully perform the upload operation from the application
  • Sample SNS standard topic in the region of your choice. I preferred to choose one in ap-south-1 region

2.2 Setting up the implementation

Let us write the different files which will be required for practical learning.

2.2.1 Setting up dependencies

Navigate to the project directory and run npm init -y to create a package.json file. This file holds the metadata relevant to the project and is used for managing the project dependencies, script, version, etc. Add the following code to the file wherein we will specify the required dependencies.

package.json

{
  "name": "node-awssns-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "aws-sdk": "^2.972.0",
    "express": "^4.17.1",
    "lodash": "^4.17.21"
  }
}

To download the dependencies navigate to the directory path containing the file and use the npm install command. If everything goes well the dependencies will be loaded inside the node_modules folder and you are good to go with the further steps.

2.2.2 Setting up AWS credentials profile

Once the IAM CLI user is created in the AWS console and the access key and secret key are copied to the clipboard we will set these attributes in the AWS credentials file locally.

Sample aws credentials file

[default]
aws_access_key_id = YOUR_CLI_USER_ACCESS_KEY
aws_secret_access_key = YOUR_CLI_USER_SECRET_KEY

2.2.3 Setting up Environment configuration

In the root folder create a folder named config and add the following content to the env.js file. The file will contain the details of the CLI user, Region, and AWS SNS details and you are free to change as per your configuration

env.js

const env = {
  PROFILE: "YOUR_AWS_CREDENTIALS_PROFILE_NAME",
  REGION: "YOUR_AWS_REGION",
  SNS: {
    PROTOCOL: "EMAIL",
    TOPIC_ARN: "YOUR_SNS_TOPIC",
  },
};

module.exports = env;

2.2.4 Creating a controller

In the root folder add the following content to the index.js file. The file will consist of the following endpoints and the application will be running on the port number – 6000.

  • Get SNS status
  • Subscribe to a topic – Will take a request body containing the email address
  • Get the status of the subscriptions attached to the topic
  • Publish an email notification via SNS topic – Will take a request body containing the email subject and message

index.js

const _ = require("lodash");
const env = require("./config/env");

const express = require("express");
const app = express();
app.use(express.json());

// Config AWS
const AWS = require("aws-sdk");
const credentials = new AWS.SharedIniFileCredentials({
  profile: env.PROFILE,
});
const sns = new AWS.SNS({
  credentials: credentials,
  region: env.REGION,
});

// Routes

// endpoint - get sns status
// http://localhost:6000/status
app.get("/status", (req, res) => {
  res.status(200).json({
    status: "ok",
    data: sns,
  });
});

// endpoint - subscribe to sns topic via email
// http://localhost:6000/subscribe
app.post("/subscribe", (req, res) => {
  let params = {
    Protocol: env.SNS.PROTOCOL,
    TopicArn: env.SNS.TOPIC_ARN,
    Endpoint: req.body.email,
  };

  sns.subscribe(params, (err, data) => {
    if (err) {
      res.status(500).json({
        status: "500",
        err: err,
      });
    } else {
      res.status(200).json({
        status: "ok",
        data: data,
      });
    }
  });
});

// endpoint - get subscription status attached to the topic
// http://localhost:6000/subscription/list
app.get("/subscription/list", (req, res) => {
  let param = {
    TopicArn: env.SNS.TOPIC_ARN,
  };

  sns.listSubscriptionsByTopic(param, (err, data) => {
    if (err) {
      res.status(500).json({
        status: "500",
        err: err,
      });
    } else {
      // console.log(data);
      let subscriptions = [];
      _.forEach(data.Subscriptions, (ele) => {
        let item = {
          protocol: _.upperCase(ele.Protocol),
          endpoint: censorEmail(ele.Endpoint),
          confirmed: isConfirmed(ele.SubscriptionArn),
        };

        subscriptions.push(item);
      });

      res.status(200).json({
        status: "ok",
        data: subscriptions,
      });
    }
  });
});

// endpoint - publish an email notification via sns topic
// all the subscriptions attached to the topic will receive the notification
// http://localhost:6000/publish
app.post("/publish", (req, res) => {
  let params = {
    Subject: req.body.subject,
    Message: req.body.message,
    TopicArn: env.SNS.TOPIC_ARN,
  };

  sns.publish(params, function (err, data) {
    if (err) {
      res.status(500).json({
        status: "500",
        err: err,
      });
    } else {
      res.status(200).json({
        status: "ok",
        data: data,
      });
    }
  });
});

// -- private methods --
let censorWord = function (str) {
  return str[0] + "*".repeat(str.length - 2) + str.slice(-1);
};

let censorEmail = function (email) {
  let arr = email.split("@");
  return censorWord(arr[0]) + "@" + censorWord(arr[1]);
};

let isConfirmed = function (status) {
  return _.isEqual(status, "PendingConfirmation") ? false : true;
};

// starting the server
const port = 6000;
app.listen(port, () => {
  console.log(`SNS app listening on port ${port}`);
});

3. Run the Application

To run the application navigate to the project directory and enter the following command as shown in Fig. 2. If everything goes well the application will be started successfully on port number 6000.

aws sns publish - starting the app
Fig. 2: Starting the application

4. Demo

You are free to use postman or any other tool of your choice to make the HTTP request to the application endpoints.

Endpoints

// HTTP GET – get sns status
http://localhost:6000/status

// HTTP POST – subscribe to sns topic via email
// Sample request - { "email": "testcartmail1@gmail.com" }
http://localhost:6000/subscribe

// HTTP GET - get subscription status attached to the topic
http://localhost:6000/subscription/list

// HTTP POST - publish an email notification via sns topic
// Sample request - { "subject": "hello world", "message": "welcome" }
http://localhost:6000/publish

That is all for this tutorial and I hope the article served you with whatever you were looking for. Happy Learning and do not forget to share!

5. Summary

In this tutorial, we saw publishing and subscribing to AWS SNS Messages with Node.js. We learned about SNS and how to create a simple express.js application to communicate with AWS SNS. This application exposes 4 endpoints to perform different tasks as mentioned in the controller file. You can download the source code and the postman collection from the Downloads section.

6. Download the Project

This was a tutorial to implement a notification service functionality in the node.js application.

Download
You can download the full source code of this example here: Publishing & Subscribing to AWS SNS Messages with Node.js

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button