Node.js AWS SNS订阅,确认

时间:2017-11-02 06:55:18

标签: javascript node.js amazon-web-services

我试图将SNS主题连接到我的Meteor(节点)JS应用程序,但是当我尝试订阅和填充时,我似乎没有得到正确的响应。

我对此事几乎没有疑问。但首先,这是我的主题和代码:

  • 我在SNS中创建了一个主题,并得到了它的ARN。
  • 我将AMI政策设定为 能够使用SNS。获得了我的访问密钥和密钥
  • 在我的LOCALHOST服务器上写了这个:

    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
    });
    
  

我此时仍然在LOCALHOST上运行我的节点应用程序

然后我切换到我的AWS SNS面板并创建订阅,选择HTTP作为协议并输入ENDPOINT URL。

第一个问题 有没有可能我可以让它在localhost上运行而不将其移动到实时服务器,如果是这样的话?

所以当我运行应用程序时,我在控制台中收到此消息:

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

我切换到我的AWS面板,我看到enter image description here

即使我将所有这些移动到实时服务器,使用相同的数据,我也会收到此待处理消息。我不知道该怎么做!

3 个答案:

答案 0 :(得分:2)

您需要确认订阅。

订阅终端后,Amazon SNS将向终端发送订阅确认消息。您应该已经拥有执行部署到端点的步骤1中所述操作的代码。具体来说,端点上的代码必须从订阅确认消息中检索SubscribeURL值,并访问SubscribeURL本身指定的位置或使其可供您使用,以便您可以手动访问SubscribeURL,例如,使用Web浏览器。在确认订阅之前,Amazon SNS不会向端点发送消息。当您访问SubscribeURL时,响应将包含一个XML文档,其中包含一个元素SubscriptionArn,用于指定订阅的ARN。您还可以使用Amazon SNS控制台验证订阅是否已确认:订阅ID将显示订阅的ARN,而不是您首次添加订阅时看到的PendingConfirmation值。

Sending Amazon SNS Messages to HTTP/HTTPS Endpoints

答案 1 :(得分:0)

如果您需要确认已订阅SNS主题,则可以通过SNS发送的请求使用AWS-NODE-SDK

{
  "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"
}

要进行确认,您将需要在正文中找到的标头和令牌中的TopicArn:

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);
  

注意:AWS将把SubscriptionConfirmation&Notifications发送到同一端点,您可以使用标头'x-amz-sns-message-type'

进行区分。

答案 2 :(得分:0)

我为打字稿制作了一个函数来确认订阅。只需从快速路线中传递您的标题和正文即可。

此外,sns请求的内容类型类似于text/plain,大多数快递应用中使用的bodyParser不会处理主体,因此body.Token将为空。为了解决这个问题,请在正文解析器使用一个中间件来增加传入的请求。

处理订阅确认

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);
        });
    }))

}

Subscription确认内容类型修饰符

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