Как вы получаете доступ к телу сообщения Amazon SNS с помощью Express/Node.js

Сейчас я перестраиваю приложение PHP в Node.js поверх Express.

Одна часть приложения - это URL-адрес обратного вызова, на который отправлено уведомление об анонсах Amazon.

Тело POST из SNS в настоящее время читается следующим образом в PHP (который работает):

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

В Express я пробовал следующее:

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

Однако, наблюдая за консолью, это только регистрируется при создании сообщения:

{}

Итак, чтобы повторить вопрос: как вы получаете доступ к телу сообщения Amazon SNS с помощью Express/ Node.js

Ответ 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.

Ответ 2

Это основано на ответе AlexGad. В частности, этот комментарий:

Стандартный экспресс-парсер будет обрабатывать только приложения /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
     }
   });

EDIT: проблема заключается в том, что стандартный синтаксический анализатор тела не обрабатывает plain/text, который 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.

Вы также можете изменить синтаксический анализатор тела для обработки текста/простого текста, но это не отличная идея для изменения промежуточного программного обеспечения. Просто используйте приведенный выше код.