Azure Bot Connector服务收消息正常但返回404错误求助
看起来你已经实现了Bot Connector的消息转发逻辑,但日志里的404确实挺让人头疼的。结合你的代码和Bot Framework的工作机制,我整理了几个最可能的原因和对应的解决办法:
1. 请求路径不匹配(带末尾斜杠)
虽然Express默认允许路径带或不带斜杠,但如果Azure Bot通道注册里的Messaging endpoint末尾加了斜杠(比如https://your-service/bot/messages/),Bot Framework发送的请求就会带上这个斜杠,而你的路由是/bot/messages(不带斜杠),某些情况下会导致路由匹配失败,返回404。
解决办法:
- 先检查Azure Bot通道注册的Messaging endpoint,确保它是
https://your-service/bot/messages(不带末尾斜杠); - 或者在
bot.js里额外注册一个兼容带斜杠的路由:// 同时支持带/不带斜杠的请求 router.post('/messages', connector.listen()); router.post('/messages/', connector.listen());
2. ChatConnector验证失败导致请求未被处理
如果MICROSOFT_APP_ID或MICROSOFT_APP_PASSWORD配置错误,ChatConnector会拒绝处理请求,请求会继续向下传递,没有匹配到其他路由就会返回404(虽然通常验证失败会返回401,但某些边缘情况会表现为404)。
解决办法:
- 核对
config.mbf里的MICROSOFT_APP_ID和MICROSOFT_APP_PASSWORD,确保和Azure Bot通道注册里的内容完全一致(注意大小写、空格,不要有多余字符); - 可以临时关闭验证做测试(仅用于排查问题,生产环境不要这么做):
如果关闭后404消失,说明就是配置的问题。var connector = new builder.ChatConnector({ appId: null, appPassword: null });
3. 异步业务逻辑未等待完成
如果routerClient.sendToRouter(activity)是异步函数,而你没有等待它完成,可能导致会话处理提前结束,但Bot Framework没有收到正确的200响应,进而触发重试请求,重试时可能因为某种原因无法匹配路由。
解决办法:
把会话处理函数改成异步,等待sendToRouter完成:
var bot = new builder.UniversalBot(connector, async function (session) { var activity = messageToActivity(session.message); await routerClient.sendToRouter(activity); // 等待异步操作完成 }).set('storage', inMemoryStorage);
4. 缺少OPTIONS请求处理(CORS预检查)
Bot Framework可能会发送OPTIONS请求做CORS预检查,如果你的服务没有处理OPTIONS请求,会返回404,有时候可能会被日志混在POST请求里。
解决办法:
修改app.js里的CORS中间件,专门处理OPTIONS请求:
app.use(function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); // 生产环境建议限制为特定域名 res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); if (req.method === 'OPTIONS') { res.sendStatus(200); return; } next(); });
调试建议
为了更精准定位问题,可以在bot.js的路由前加一个日志中间件,记录所有到达/bot/messages的请求细节:
// 在bot.js的router.post之前添加 router.use('/messages', function(req, res, next) { console.log(`Received ${req.method} request to full path: ${req.originalUrl}`); console.log('Request headers:', JSON.stringify(req.headers, null, 2)); next(); });
这样你就能看到请求的完整路径、方法和头信息,更容易找到问题所在。
内容的提问来源于stack exchange,提问作者ThinkFloyd

