【问题标题】:How do you access an Amazon SNS post body with Express / Node.js如何使用 Express / Node.js 访问 Amazon SNS 帖子正文
【发布时间】:2020-04-15 02:39:51
【问题描述】:

我正在 Express 框架之上的 Node.js 中重建 PHP 应用程序。

应用程序的一部分是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);
});

但是,查看控制台,这只会在发布帖子时记录以下内容:

{}

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

【问题讨论】:

标签: node.js express amazon-sns


【解决方案1】:

另一种方法是修复 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

【讨论】:

  • 这是一个很好的答案,特别是如果您想使用同一个应用程序来处理来自 SNS 的通知和订阅确认。
  • docs.aws.amazon.com/sns/latest/dg/… AWS 使用 text/plain 作为 Content-Type 是否有原因?处理这个真的很头疼。很高兴有一个解决方案
  • 查看this topic 并得出自己的结论。注意日期。与其尝试寻找替代方案来解决该问题,不如让 AWS 解决它。
【解决方案2】:

这是基于 AlexGad 的回答。特别是这条评论:

标准的 express 解析器只会处理 application/json、application/x-www-form-encoded 和 multipart/form-data。我在上面添加了一些代码放在您的正文解析器之前。

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('') )
    })  
})

【讨论】:

  • 技术上正确,投票较高的帖子是指定问题的“更清洁”解决方案。让经过良好测试的框架完成这项工作......
【解决方案3】:

看看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 帖子进行操作。

您还可以修改正文解析器以处理文本/纯文本,但修改中间件不是一个好主意。只需使用上面的代码即可。

【讨论】:

  • 我认为这可能是一个更早的阶段。我的应用程序已经订阅。正如我在控制台中看到的那样,SNS 确实会发布到它,但我无法访问帖子的正文。
  • 啊,抱歉。我现在明白你在做什么了。我相信 SNS 将内容作为文本/纯文本发送,即使文本是 JSON 格式。你是如何设置你的身体解析器的?标准的 express 解析器只会处理 application/json、application/x-www-form-encoded 和 multipart/form-data。我在上面添加了一些代码放在您的正文解析器之前。它会根据您的请求为您提供一个原始正文,您可以对其进行测试以确保您从 SNS 获取数据。记录此内容,然后您可能必须编写自己的正文解析器。
  • 我无法让它工作。然而,它确实为我指明了 req.on 和分块的正确方向,所以感谢您的输入。我已将我的解决方案作为公认的答案。
【解决方案4】:

假设您正在使用 body-parser,您可以这样做。

只需将以下行添加到您的 app.js 中:

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

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

【讨论】:

  • +1 添加这两个选项都适用于我的用例,因为我需要 json 来发送邮件,并且从 AWS 退回返回 text/plain 类型。
猜你喜欢
  • 2012-07-22
  • 1970-01-01
  • 2018-10-09
  • 1970-01-01
  • 2015-06-03
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多