Reputation: 360
I'm having trouble parsing Amazon SNS HTTP POST body data. I'm using the Iron Router plugin to run an HTTP endpoint.
The problem is Iron Router depends on the Connect npm module, which only parses requests with the following Content-Types:
application/json
application/x-www-form-urlencoded
multipart/form-data
Amazon SNS sends all of it's data encoded in text/plain, so custom middleware is needed to parse the body, as documented here: Handling text/plain in Express 3 (via connect)?.
How can I adapt this solution to Meteor or Iron Router?
Upvotes: 1
Views: 628
Reputation: 966
An even easier solution has been introduced by Amazon SNS today. Amazon SNS now supports custom Content-Type
headers for HTTP messages delivered from topics. Here's the feature announcement: https://aws.amazon.com/about-aws/whats-new/2023/03/amazon-sns-content-type-request-headers-http-s-notifications/
As you can see, you basically need to modify the DeliveryPolicy
attribute of your Amazon SNS subscription, setting the headerContentType
property to application/json
, application/xml
, or any other value supported. You can find all values supported here: 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"
}
}
You set the DeliveryPolicy
attribute by calling the SetSubscriptionAttributes
API action: https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html
Upvotes: 0
Reputation: 601
If anyone is still struggling with this, it is now much easier to solve by using the following:
onBeforeAction: Iron.Router.bodyParser.text()
Upvotes: 1
Reputation: 360
I solved this by accessing the connect handlers through meteor. Here's the code:
var connectHandlers;
if (typeof __meteor_bootstrap__.app !== 'undefined') {
connectHandlers = __meteor_bootstrap__.app;
}
else {
connectHandlers = WebApp.connectHandlers;
}
connectHandlers.use((function(req, res, next) {
if (req.headers['content-type'] === 'text/plain; charset=UTF-8') {
var bodyarr = [];
req.on('data', function(chunk) {
bodyarr.push(chunk);
});
req.on('end', function() {
req.body = bodyarr.join('');
next();
});
}
else {
next();
}
}));
This should be able to accept any kind of connect middleware, not just one for text/plain.
Upvotes: 2