AWS SNS订阅确认POST请求至Node.js API路由时请求体为空/未定义
解决AWS SNS订阅确认请求体在Node.js API中为空的问题
问题原因
从你提供的curl请求可以看到,AWS SNS发送的POST请求Content-Type是text/plain; charset=UTF-8,而大多数Node.js Web框架(比如Express)默认只配置了解析application/json类型的请求体,无法正确解析SNS的文本格式请求体,导致获取到空或未定义的请求体。
解决方案
1. 配置文本请求体解析中间件
如果使用Express框架,需要添加解析text类型请求体的中间件,将接收到的文本内容转换为JSON对象:
const express = require('express'); const app = express(); // 解析text/plain类型的请求体 app.use(express.text({ type: 'text/plain' })); // 将解析后的文本转为JSON对象 app.use((req, res, next) => { if (req.is('text/plain')) { try { req.body = JSON.parse(req.body); } catch (err) { console.error('解析SNS请求体失败:', err); return res.status(400).send('无效的请求体格式'); } } next(); }); // SNS通知处理路由 app.post('/api/SESNotifications', (req, res) => { console.log('收到SNS请求:', req.body); // 处理订阅确认请求 if (req.body.Type === 'SubscriptionConfirmation') { console.log('待确认订阅URL:', req.body.SubscribeURL); // 需向该URL发起GET请求完成订阅(可使用axios/node-fetch等工具) res.status(200).send('确认收到'); } else if (req.body.Type === 'Notification') { console.log('收到通知内容:', req.body.Message); res.status(200).send('处理完成'); } else { res.status(400).send('未知的消息类型'); } }); app.listen(5000, () => { console.log('服务器运行在端口5000'); });
2. 关键注意事项
- 中间件顺序不能错:先解析text内容,再转为JSON,最后处理路由
- 订阅确认必须完成:只有向
SubscribeURL发起GET请求,AWS SNS才会停止发送确认请求 - 可选添加签名验证:验证请求签名,确保请求确实来自AWS SNS,避免伪造请求
内容的提问来源于stack exchange,提问作者Rajat Agarwal
相关产品推荐
相关产品推荐

