Skip to content

Instantly share code, notes, and snippets.

@NEbere
Created October 19, 2021 14:56
Show Gist options
  • Save NEbere/97d53274aa186bd2e69ba774f0afad39 to your computer and use it in GitHub Desktop.
Save NEbere/97d53274aa186bd2e69ba774f0afad39 to your computer and use it in GitHub Desktop.
simple code to show SNS topic subscription, confirmation and notification handling via expressJS
const express = require('express')
const AWS = require("aws-sdk")
var bodyParser = require('body-parser')
const MessageValidator = require('sns-validator')
var jsonParser = bodyParser.json()
const config = {
"SNS_TOPIC_ARN": "",
"USER_ARN": "",
"USER_ACCESS_KEY_ID": "",
"USER_SECRET_ACCESS_KEY": "",
"DLQ_ARN": ""
};
// exponential backoff retry times = 20 - 3 - 2 - 5 = 20 - 10 = 10
// 10 times retry (with exponential backoff from 1 second to 60 seconds)
const deliveryPolicy = {
"healthyRetryPolicy": {
"minDelayTarget": 1,
"maxDelayTarget": 60, // maximum value of 3,600 seconds
"numRetries": 20, // The total number of retries, including immediate, pre-backoff, backoff, and post-backoff retries. max of 100
"numNoDelayRetries": 3, // retry 5 times immediately in the no-delay phase
"numMinDelayRetries": 2, // retry 2 times, 1 second apart in the pre-backoff phase
"numMaxDelayRetries": 5, // 10 times 60 seconds apart in the post-backoff phase
"backoffFunction": "exponential"
},
}
const redrivePolicy = {
"deadLetterTargetArn": config.DLQ_ARN
}
const app = express()
const port = 3030
app.use(
express.json({
type: [
'application/json',
'text/plain', // AWS sends this content-type for its messages/notifications
],
})
)
// const credentials = new AWS.SharedIniFileCredentials({profile: 'sns_profile'});
const SNS = new AWS.SNS({
credentials: {
accessKeyId: config.USER_ACCESS_KEY_ID,
secretAccessKey: config.USER_SECRET_ACCESS_KEY,
},
region: 'eu-central-1'
})
app.get('/', (req, res) => {
res.send({ response: 'Hello World!' })
})
// Endpoint used to create subscription via http request
app.post('/subscribe', (req, res) => {
let params = {
Protocol: 'HTTPS',
TopicArn: config.SNS_TOPIC_ARN,
Endpoint: '',
Attributes: {
DeliveryPolicy: JSON.stringify(deliveryPolicy),
RedrivePolicy: JSON.stringify(redrivePolicy)
},
ReturnSubscriptionArn: true
};
SNS.subscribe(params, (err, data) => {
if (err) {
console.log({err, msg: "error subscribing to topic"});
} else {
console.log(data);
res.send({data, msg: "success to topic"});
}
});
});
// function used to call the confirmSubscription action on SNS
const confirmSubscription = (request) => {
console.log('running confirmSubscription', request.body)
const { Token, TopicArn } = request.body
const params = {
Token,
TopicArn
}
SNS.confirmSubscription(params, function(err, data) {
if (err) console.log({err, stack: err.stack, message: "error confirming subscription"}); // an error occurred
else console.log({data, message:"successfuly confirmed subscription"}); // successful response
});
}
// The HTTP endpoint registered on AWS for
app.post('/notifications', jsonParser, (req, res) => {
const validator = new MessageValidator();
const messageType = req.body.Type
validator.validate(req.body, function (err, message) {
if (err) {
// Your message could not be validated.
console.log(err, 'error validating message')
return;
}
// SNS subscription confirmation
if (messageType == 'SubscriptionConfirmation') {
confirmSubscription(req)
console.log({body:req.body, messageType})
}
// SNS notifications
if (messageType == 'Notification') {
const { Message} = req.body
console.log({messageType, Message:JSON.parse(Message)})
}
});
// res.sendStatus(500).send({message: 'cannot process request'})
res.send("success")
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment