Publicación y suscripción a mensajes de AWS SNS con Node.js

AWS SNS es un servicio escalable que nos permite implementar el modelo de publicación/suscripción con facilidad. En este tutorial, crearemos una aplicación Node.js, nos suscribiremos a un tema de SNS y enviaremos mensajes a los suscriptores.

Introducción

Mucha de la tecnología que vemos se basa en un ciclo de solicitud/respuesta muy inmediato: cuando realiza una solicitud a un sitio web, obtiene una respuesta que contiene el sitio web que solicitó, idealmente de inmediato. Todo esto depende de que el usuario tome la decisión activa de solicitar esos datos.

A veces, necesitamos desviarnos de ese modelo, y para eso usamos el modelo 'publicar/suscribir'. Servicio de notificación simple de AWS (SNS) es un servicio súper escalable que permite a los usuarios implementar el modelo de publicación/suscripción con facilidad. Esto nos permite enviar mensajes de texto, correos electrónicos, notificaciones automáticas u otros mensajes automáticos a otros objetivos a través de múltiples canales al mismo tiempo.

En esta publicación, aprenderemos cómo crear una aplicación web que pueda publicar un mensaje para varios suscriptores a la vez por correo electrónico, todos usando SNS.

Obviamente necesitarás una cuenta de Servicios web de Amazon (AWS) para hacer esto. Y afortunadamente, SNS tiene un nivel gratuito en el que sus primeras 1 millón de notificaciones automáticas de SNS son gratuitas cada mes.

Modelo de publicación/suscripción

El modelo de publicación/suscripción consta de dos componentes en un sistema:

  • Editor: un servicio que puede transmitir mensajes a otros servicios que lo escuchan (suscrito).
  • Suscriptor: Cualquier servicio al que el editor transmitirá.

Para convertirse en suscriptor, un servicio debe notificar al editor que desea recibir sus transmisiones, así como también dónde desea recibir esas transmisiones; en ese momento, el editor lo incluirá en su lista de objetivos la próxima vez que publica un mensaje.

Una buena metáfora para el modelo de publicación/suscripción es cualquier boletín al que te hayas suscrito. En este caso, ha ido activamente al editor y le ha dicho que desea suscribirse y le ha dado su correo electrónico.

Nada se hace inmediatamente una vez que se ha suscrito y no recibe ningún número anterior del boletín.

La próxima vez que el editor publica un mensaje (envía su boletín mensual), llega un correo electrónico. Luego puede elegir hacer lo que quiera con el correo electrónico: puede eliminarlo, leerlo o incluso actuar sobre algunos de los detalles que contiene.

Configuración de un tema de SNS

Para comenzar, primero debemos configurar un tema en AWS SNS. Un tema es lo que consideraríamos un 'editor': podemos enviar mensajes a un tema, que luego publicará para todos sus suscriptores.

En su panel de AWS, seleccione 'Simple Notification Service' y presione 'Temas' en el lado izquierdo, seguido del botón 'Crear tema'.

Se le presentará una pantalla que le pedirá que proporcione información básica sobre el tema SNS:

Create Topic Image

Esta pantalla tiene varias opciones, aunque solo muestra un grupo de forma predeterminada: este es el nombre (que es obligatorio) y el nombre para mostrar, que se puede configurar opcionalmente; se usa si desea publicar para suscriptores de SMS desde el tema.

Algunas de las otras opciones incluyen:

  • Cifrado de mensajes: Cifrado de mensajes después de ser enviados por el editor. Esto realmente solo es útil si está enviando datos personales/muy confidenciales.
  • Políticas de Acceso: Define exactamente quién puede publicar mensajes en el tema.
  • Política de reintento: en caso de que un suscriptor no reciba un mensaje publicado por cualquier motivo.
  • Registro de estado de entrega: le permite configurar un rol IAM (Administración de identidad y acceso) en AWS que escribe registros de estado de entrega en [AWS Cloud Watch](https://aws.amazon.com /vigilancia en la nube/).

Por ahora, vamos a completar un nombre y un nombre para mostrar, luego nos desplazaremos hasta la parte inferior y presionaremos 'Crear tema'. Tome nota del ARN del tema recién creado, ya que lo necesitaremos eso mas tarde.

Configuración de un usuario de IAM

Usaremos el SDK de JavaScript de AWS para interactuar con AWS SNS, y para poder hacerlo,\ Necesitará un conjunto de credenciales que el SDK puede usar para enviar solicitudes a AWS.

Podemos obtener este conjunto de credenciales creando un usuario IAM. Abra el menú 'Services' que usamos para buscar anteriormente, y esta vez busque IAM.

Verás una pantalla que se ve así:

IAM Main View

Haga clic en 'Usuarios' a la izquierda, luego haga clic en 'Agregar usuario' - verá una pantalla como esta:

SNS user creation

A modo de tutorial, vamos a crear un usuario con el nombre SNSUser y marque la casilla de acceso programático. Querremos acceder a él a través de nuestra aplicación mediante programación, no solo a través de la consola de AWS.

Esto permite que cualquier persona con las credenciales acceda a partes específicas de AWS a través de la CLI o el SDK de JavaScript que vamos a utilizar. No necesitamos darles acceso a la consola de administración de AWS, ya que no planeamos que esas credenciales interactúen con AWS a través de un navegador, como lo está haciendo ahora.

Haga clic en Siguiente y se le presentarán los permisos. Haga clic en el botón 'Adjuntar políticas existentes directamente' y al buscar 'SNS', podrá encontrar fácilmente la opción 'SNSFullAccess':

Attach policy view

Los usuarios, roles y políticas de IAM son un gran tema que definitivamente vale la pena investigar; sin embargo, por ahora, esto debería funcionar para nosotros.

Al presionar 'Siguiente: Etiquetas' en la esquina inferior derecha, y luego 'Siguiente: Revisar' en la misma ubicación, debería ver una pantalla de resumen similar a esta:

IAM user review

Nota: Asegúrese de copiar la Identificación de la clave de acceso y la Clave de acceso secreta o descargar el archivo CSV, ya que esta es la única vez que puede obtener estas credenciales; de lo contrario, deberá crear un nuevo usuario.

Mientras hablamos de credenciales, asegúrese de no publicar estas credenciales en ningún lugar en línea, ni enviarlas a un repositorio de Git. Los malos actores buscarán en GitHub repositorios con credenciales en ellos para que puedan acceder y usar recursos en su cuenta de AWS, lo que le costará algo de dinero.

Finalmente, configuraremos nuestras credenciales localmente (Linux/OSX/Unix) para que nuestra aplicación Node pueda usarlas en el siguiente paso.

Para determinar su región, visite esta página y encuentre la región más cercana a usted. El valor predeterminado en AWS es us-east-2, que tiene su sede en Ohio. Esta es la región que verá cuando vea AWS en su navegador:

1
2
3
4
5
touch ~/.aws/credentials
echo '[sns_profile]' >> ~/.aws/credentials
echo 'aws_access_key_id = <YOUR_ACCESS_KEY_ID>' >> ~/.aws/credentials # The access key ID from the IAM user
echo 'aws_secret_access_key = <YOUR_SECRET_ACCESS_KEY>' >> ~/.aws/credentials # The secret access key from the IAM user
echo 'region = <YOUR_AWS_REGION>' # From the regions page, examples include: us-east-1, us-west-1, eu-west-1, etc.

Demostración de la aplicación Node.js

A continuación, vamos a crear una aplicación de nodo usando Express. Esta aplicación tendrá dos puntos finales. El primero será para agregar direcciones de correo electrónico como suscriptores a nuestro tema, el segundo será para enviar un correo electrónico a todos nuestros suscriptores.

Nota: mientras usamos el punto final de correo electrónico en esta demostración, se puede usar el mismo código general para cualquiera de los otros puntos finales de SNS, como HTTP, SMS, Lambda, etc. Solo necesita intercambiar un pocos parámetros en la llamada a la API de SNS.

En primer lugar, creemos una carpeta para nuestro proyecto en nuestra terminal, vayamos al directorio e inicialicemos nuestra aplicación Node:

1
2
3
$ mkdir node-sns-app
$ cd node-sns-app
$ npm init

Puede presionar Intro hasta que el script se complete con las opciones predeterminadas, haciendo que nuestro punto de entrada predeterminado sea index.js.

A continuación, necesitamos instalar los módulos Express y AWS-SDK para poder usarlos a ambos:

1
2
$ npm install express --save
$ npm install aws-sdk --save

A continuación, queremos crear nuestra aplicación. En el mismo directorio, crea un archivo llamado index.js:

1
$ touch index.js

Primero, pondremos algo de código solo para asegurarnos de que podemos ejecutar la aplicación con AWS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const express = require('express');
const app = express();

const AWS = require('aws-sdk');
const credentials = new AWS.SharedIniFileCredentials({profile: 'sns_profile'});
const sns = new AWS.SNS({credentials: credentials, region: 'eu-west-2'});

const port = 3000;

app.use(express.json());

app.get('/status', (req, res) => res.json({status: "ok", sns: sns}));

app.listen(port, () => console.log(`SNS App listening on port ${port}!`));

La mayor parte de esto es repetitivo para Express, pero las líneas 4-6 crean una instancia de AWS, le dicen que use las credenciales en el perfil que creamos en ~/aws/credentials anteriormente, y cree una instancia de la clase SNS con él.

Ahora, podemos continuar y ejecutar el archivo:

1
$ node index.js

Visitar localhost:3000/status imprimirá una gran parte de JSON que tiene sus credenciales de AWS. Si eso funciona, entonces podemos continuar y crear nuestros puntos finales.

Extremo de suscripción

Primero, necesitamos agregar un punto final POST para agregar suscriptores; en este caso, nuevas direcciones de correo electrónico. Debajo del punto final /status, agregaremos el punto final /subscribe:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
app.post('/subscribe', (req, res) => {
    let params = {
        Protocol: 'EMAIL', 
        TopicArn: '<YOUR_TOPIC_ARN_HERE>',
        Endpoint: req.body.email
    };

    sns.subscribe(params, (err, data) => {
        if (err) {
            console.log(err);
        } else {
            console.log(data);
            res.send(data);
        }
    });
});

Bien, analicemos esto. Primero, estamos creando un punto final POST. Dentro de ese punto final, estamos creando una variable de parámetros lista para entregar a nuestra solicitud de suscripción a SNS.

La variable de parámetros necesita algunas cosas:

  • Protocolo: lo hemos configurado como correo electrónico, pero podría ser HTTP/S, SMS, SQS (si desea utilizar el servicio de cola de AWS), o incluso una función Lambda
  • TopicArn: este es el ARN, un identificador único para el tema de SNS que configuró anteriormente. Si no lo tiene, vaya y tómelo de su Tema en su navegador y péguelo en el código ahora.
  • Endpoint: El tipo de punto final depende del protocolo. Debido a que estamos enviando correos electrónicos, le daríamos una dirección de correo electrónico, pero si estuviéramos configurando una suscripción HTTP/S, en su lugar, pondríamos una dirección URL o un número de teléfono para SMS.

Puede leer más sobre el método de suscripción de la documentación oficial.

Una vez que esto esté dentro, inicie su servidor nuevamente. Deberá enviar una solicitud con un cuerpo JSON a su aplicación; puede hacerlo con herramientas como Cartero, o si lo prefiere, puede hacerlo en la CLI:

1
$ curl -H "Content-type: application/json" -d '{ "email": "<AN_EMAIL_ADDRESS_HERE>" }' 'localhost:3000/subscribe'

Si el punto de enlace y el mensaje son correctos, esa dirección de correo electrónico recibirá un correo electrónico que le preguntará si desea confirmar su suscripción; cualquier suscripción creada a través de AWS SNS debe ser confirmada por el punto de enlace de alguna forma, de lo contrario, AWS podría usarse de forma malintencionada para enviar spam o Ataques tipo DDOS.

Asegúrese de confirmar la suscripción antes del siguiente paso para cualquier correo electrónico al que se suscriba.

Punto final de correo electrónico

Ahora para hacer el punto final para enviar nuestro correo electrónico:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
app.post('/send', (req, res) => {
    let params = {
        Message: req.body.message,
        Subject: req.body.subject,
        TopicArn: '<YOUR_TOPIC_ARN_HERE>'
    };

    sns.publish(params, function(err, data) {
        if (err) console.log(err, err.stack); 
        else console.log(data);
    });
});

Nuevamente, echemos un vistazo a de qué están hechos los parámetros aquí:

  • Mensaje: este es el mensaje que desea enviar; en este caso, sería el cuerpo del correo electrónico
  • Asunto: este campo solo se incluye porque estamos enviando un correo electrónico; esto establece el asunto del correo electrónico
  • TopicArn: este es el tema en el que estamos publicando el mensaje; se publicará en todos los suscriptores de correo electrónico de ese tema.

Si quieres saber más sobre el método de publicación, echa un vistazo a la documentación, también hay [otras propiedades](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SNS.html#publish -propiedad).

Puede enviar un mensaje ahora usando Postman, o curl, siempre que estemos pasando nuestros parámetros para el asunto y el mensaje:

1
$ curl -H "Content-type: application/json" -d '{ "subject": "Hello there!", "message": "You just received an email from SNS!" }' 'localhost:3000/send'

Una vez que se realiza esta solicitud, todos los suscriptores del punto final deben recibir este correo electrónico. ¡Felicitaciones, acaba de publicar su primer mensaje usando SNS y Node.js!

¿Qué sigue? {#qué sigue}

Plantillas de mensajes

Al ver que su mensaje es una cadena, podría usar la interpolación de cadenas para la entrada dinámica, por ejemplo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
app.post('/send', (req, res) => {
    let now = new Date().toString();
    let email = `${req.body.message} \n \n This was sent: ${now}`;
    let params = {
        Message: email,
        Subject: req.body.subject,
        TopicArn: '<YOUR_TOPIC_ARN_HERE'
    };

    sns.publish(params, function(err, data) {
        if (err) console.log(err, err.stack); 
        else console.log(data);
    });
});

Puntos finales HTTP

Puede configurar un servicio diseñado para recibir el mensaje, en caso de que desee activar una acción en segundo plano, pero no necesariamente se preocupa por recibir el resultado de inmediato. Simplemente establezca el punto final como HTTP/S y podrá formatear el mensaje como desee. Por ejemplo, esto es especialmente útil para servidores/servicios sobre los que quizás no tenga control, pero que le permitan enviar notificaciones de webhook.

lambda

De manera similar, podría usar estos mensajes para activar y entregar entradas a las funciones de Lambda. Esto podría iniciar un trabajo de procesamiento, por ejemplo. ¡Echa un vistazo a esta publicación para saber cómo!

SMS

Si elimina el campo asunto, puede enviar mensajes SMS de 160 caracteres a cualquier número de teléfono suscrito.

SQS

Con el tipo de punto final de SQS, puede colocar mensajes en colas para crear arquitecturas basadas en eventos: eche un vistazo a Este artículo ¡para más detalles!

¿Mensajes mixtos? {#mensajes mixtos}

Hay un parámetro MessageStructure que puede entregar que le permite usar en Topic para transmitir en múltiples canales con diferentes mensajes; esto significa que puede escribir un correo electrónico completo para todos los suscriptores de correo electrónico, pero al mismo tiempo enviar un mensaje que está optimizado para SMS a todos los suscriptores móviles, lo que permite múltiples canales de comunicación.

Conclusión

Servicio de notificación simple de AWS (SNS) es un servicio súper escalable que permite a los usuarios implementar el modelo de publicación/suscripción con facilidad. Esto nos permite enviar mensajes de texto, correos electrónicos, notificaciones automáticas u otros mensajes automáticos a otros objetivos a través de múltiples canales al mismo tiempo.

En este artículo, creamos un tema y nos suscribimos a él mediante programación utilizando el SDK de AWS de Node.js. Luego creamos puntos finales HTTP en nuestra aplicación de demostración que permite a los usuarios suscribirse a nuestro tema SNS por correo electrónico y otro punto final para transmitir un correo electrónico a todos los suscriptores. es.