简体   繁体   中英

Node.js AWS SNS subscription , confirmation

I'm trying to connect an SNS topic to my Meteor ( node ) JS application, but it seems like i'm not getting the right response when i try to subscribe and stuff.

I have few questions regarding this matter. but first , this is my topic and code :

  • I created a topic in SNS, and got it's ARN.
  • I Set my AMI Policy to be able to use SNS. Got my access key and secret key
  • Wrote this on my LOCALHOST server :

     AWS.config.update({ accessKeyId: 'something', secretAccessKey: 'someotherthing+a4f23', region: 'eu-west-1' }); let sns = new AWS.SNS(); var params = { Protocol: 'http', /* required */ TopicArn: 'arn:aws:sns:eu-west-1:888472248156:ps-tracking', /* required */ Endpoint: 'http://URL:4000' }; sns.subscribe(params, function(err, data) { if (err) console.log(err, err.stack); // an error occurred else console.log(data); // successful response });

I'm still running my node app on LOCALHOST at this point

then i switch to my AWS SNS panel and create a subscription, choose HTTP as protocol and type in the ENDPOINT URL.

First Question Is there any possibility that i can get this to work on localhost without moving it to the live server, if so how ?

so when i run the appliction i get this message in the console :

{ ResponseMetadata: { RequestId: '64a88abb-7997-5f47-bfcc-d8cfc5281ca3' },
 SubscriptionArn: 'pending confirmation' }

i switch to my AWS panel i see在此处输入图片说明

even when i move all this to the live server, with the same data, i'm getting this pending message. and i don't know what i should do !

You need to confirm the subscription.

After you subscribe your endpoint, Amazon SNS will send a subscription confirmation message to the endpoint. You should already have code that performs the actions described in Step 1 deployed to your endpoint. Specifically, the code at the endpoint must retrieve the SubscribeURL value from the subscription confirmation message and either visit the location specified by SubscribeURL itself or make it available to you so that you can manually visit the SubscribeURL, for example, using a web browser. Amazon SNS will not send messages to the endpoint until the subscription has been confirmed. When you visit the SubscribeURL, the response will contain an XML document containing an element SubscriptionArn that specifies the ARN for the subscription. You can also use the Amazon SNS console to verify that the subscription is confirmed: The Subscription ID will display the ARN for the subscription instead of the PendingConfirmation value that you saw when you first added the subscription.

Sending Amazon SNS Messages to HTTP/HTTPS Endpoints

I made an function for typescript to confirm the subscription. Just pass in your header and body from the express route.

Also the content type of the sns request is something like text/plain and the bodyParser used in most express apps won't process the body so the body.Token will be empty. To solve this use a middleware before you body parser to augment the request coming in.

Process subscription confirmation

import AWS from "aws-sdk";
const snsInstance = new AWS.SNS();

function isConfirmSubscription(headers: {
    'x-amz-sns-message-type': string
}) {
    return headers['x-amz-sns-message-type'] === 'SubscriptionConfirmation'
}

function confirmSubscription(
    headers: {
        'x-amz-sns-topic-arn': string,
        'x-amz-sns-message-type': string
},
    body: {Token: string}
): Promise<string>{

    return new Promise(((resolve, reject) =>{
        if(!isConfirmSubscription(headers)){
            return resolve('No SubscriptionConfirmation in sns headers')
        }

        snsInstance.confirmSubscription({
            TopicArn: headers['x-amz-sns-topic-arn'],
            Token : body.Token
        }, (err, res)=>{
            console.log(err);
            if(err){
                return reject(err)
            }
            return resolve(res.SubscriptionArn);
        });
    }))

}

SubscriptionConfirmation content type modifier

app.use(function(req, res, next) {
    if (req.headers['x-amz-sns-message-type']) {
        req.headers['content-type'] = 'application/json;charset=UTF-8';
    }
    next();
});

If you need to confirm the subscription to an SNS Topic, you can use the AWS-NODE-SDK using the Request sent from SNS:

{
  "Type" : "SubscriptionConfirmation",
  "MessageId" : "165545c9-2a5c-472c-8df2-7ff2be2b3b1b",
  "Token" : "2336412f37fb687f5d51e6e241d09c805a5a57b30d712f794cc5f6a988666d92768dd60a747ba6f3beb71854e285d6ad02428b09ceece29417f1f02d609c582afbacc99c583a916b9981dd2728f4ae6fdb82efd087cc3b7849e05798d2d2785c03b0879594eeac82c01f235d0e717736",
  "TopicArn" : "arn:aws:sns:us-west-2:123456789012:MyTopic",
  "Message" : "You have chosen to subscribe to the topic arn:aws:sns:us-west-2:123456789012:MyTopic.\nTo confirm the subscription, visit the SubscribeURL included in this message.",
  "SubscribeURL" : "https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-west-2:123456789012:MyTopic&Token=2336412f37fb687f5d51e6e241d09c805a5a57b30d712f794cc5f6a988666d92768dd60a747ba6f3beb71854e285d6ad02428b09ceece29417f1f02d609c582afbacc99c583a916b9981dd2728f4ae6fdb82efd087cc3b7849e05798d2d2785c03b0879594eeac82c01f235d0e717736",
  "Timestamp" : "2012-04-26T20:45:04.751Z",
  "SignatureVersion" : "1",
  "Signature" : "EXAMPLEpH+DcEwjAPg8O9mY8dReBSwksfg2S7WKQcikcNKWLQjwu6A4VbeS0QHVCkhRS7fUQvi2egU3N858fiTDN6bkkOxYDVrY0Ad8L10Hs3zH81mtnPk5uvvolIC1CXGu43obcgFxeL3khZl8IKvO61GWB6jI9b5+gLPoBc1Q=",
  "SigningCertURL" : "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem"
}

To make the confirmation you will need the TopicArn from the header & Token found on the body:

AWS.config.update({
  accessKeyId    : 'ACCESS_KEY',
  secretAccessKey: 'ACCESS_SECRET_KEY',
  region : 'region'
});
// Create S3 Object from AWS SDK
const sns = new AWS.SNS();
// Request options
let options = {
  TopicArn: req.headers['x-amz-sns-topic-arn'],
  Token : req.body.Token
}
// Confirm Token Subscription
sns.confirmSubscription(options, callback);

Note: AWS will send the SubscriptionConfirmation & Notifications to the same endpoint, you can differentiate those by using the header 'x-amz-sns-message-type'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM