如何使用Express/Node.js访问Amazon SNS帖子正文

slmsl1lt  于 2023-03-29  发布在  Node.js
关注(0)|答案(5)|浏览(104)

我正在Express框架之上的Node.js中重建一个PHP应用程序。
应用程序的一部分是一个回调url,Amazon SNS notification被发送到该url。
SNS中的POST正文当前在PHP中以以下方式读取(可以工作):

$notification = json_decode(file_get_contents('php://input'));

在Express中,我尝试了以下操作:

app.post('/notification/url', function(req, res) {
    console.log(req.body);
});

但是,通过观察控制台,这只会在执行post时记录以下内容:

{}

所以,重复一下问题:如何使用Express/Node.js访问Amazon SNS帖子正文

mzsu5hc0

mzsu5hc01#

另一种方法是修复Content-Type头。
下面是中间件代码:

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

这里假设根项目目录中有一个名为***util.js***的文件,其中包含:

util = require('./util');

在您的***app.js***中,并通过包含以下内容来调用:

app.use(util.overrideContentType());

之前

app.use(express.bodyParser());

在***app.js***文件中。这允许bodyParser()正确解析正文...
侵入性更低,您可以正常访问***req.body***。

xxb16uws

xxb16uws2#

这是基于AlexGad的回答。特别是这条评论:
标准的express解析器只处理application/json,application/x-www-form-encoded和multipart/form-data。我在上面添加了一些代码放在你的body解析器之前。

app.post('/notification/url', function(req, res) {
    var bodyarr = []
    req.on('data', function(chunk){
      bodyarr.push(chunk);
    })  
    req.on('end', function(){
      console.log( bodyarr.join('') )
    })  
})
insrf1ej

insrf1ej3#

看看AWS Node.js SDK-它可以访问所有AWS服务端点。

var sns = new AWS.SNS();

    // subscribe
    sns.subscribe({topic: "topic", Protocol: "https"}, function (err, data) {
      if (err) {
        console.log(err); // an error occurred
      } else {
        console.log(data); // successful response - the body should be in the data
     }
   });

    // publish example
    sns.publish({topic: "topic", message: "my message"}, function (err, data) {
      if (err) {
        console.log(err); // an error occurred
      } else {
        console.log(data); // successful response - the body should be in the data
     }
   });

编辑:问题是标准的正文解析器不处理SNS作为内容类型发送的纯文本,下面是提取原始正文的代码,放在你的正文解析器前:

app.use(function(req, res, next) {
    var d= '';
    req.setEncoding('utf8');
    req.on('d', function(chunk) { 
        d+= chunk;
    });
    req.on('end', function() {
        req.rawBody = d;
        next();
    });
});

然后,您可以用途:

JSON.stringify(req.rawBody));

在你的路由中创建一个javascript对象,并对SNS帖子进行适当的操作。
你也可以修改body解析器来处理text/plain,但是修改中间件不是一个好主意。

rslzwgfq

rslzwgfq4#

假设你使用body-parser,下面是你如何做到这一点。
只需将以下代码行添加到您的app.js中:

app.use(bodyParser.json());
app.use(bodyParser.text({ type: 'text/plain' }));

这些信息也可以在body-parser官方文档中找到:
https://github.com/expressjs/body-parser

nom7f22z

nom7f22z5#

这里的问题是Amazon SNS默认将Content-Type标头设置为text/plain。现在,Amazon SNS中有一个内置的解决方案,它刚刚推出了对从主题交付的HTTP消息的自定义Content-Type标头的支持。以下是发布帖子:https://aws.amazon.com/about-aws/whats-new/2023/03/amazon-sns-content-type-request-headers-http-s-notifications/
您必须修改Amazon SNS订阅的DeliveryPolicy属性,将headerContentType属性设置为application/json或支持的任何其他值。您可以在此处找到支持的所有值:https://docs.aws.amazon.com/sns/latest/dg/sns-message-delivery-retries.html#creating-delivery-policy

{
    "healthyRetryPolicy": {
        "minDelayTarget": 1,
        "maxDelayTarget": 60,
        "numRetries": 50,
        "numNoDelayRetries": 3,
        "numMinDelayRetries": 2,
        "numMaxDelayRetries": 35,
        "backoffFunction": "exponential"
    },
    "throttlePolicy": {
        "maxReceivesPerSecond": 10
    },
    "requestPolicy": {
        "headerContentType": "application/json"
    }
}

您可以通过调用SubscribeSetSubscriptionAttributes API操作来设置DeliveryPolicy属性:

或者,您也可以使用AWS::SNS::Subscription资源使用AWS CloudFormation来设置此策略。

相关问题