node.js - 用于服务页面和端点的 Express 服务器
问题描述
我希望有一个 Node Web 服务器服务页面,并设置为监听 webhook 的端点。第一个示例来自Rocket Rides,相关代码为:
const express = require('express');
// ...
const app = express();
// ...
// CRUD routes for the pilot signup and dashboard
app.use('/pilots', require('./routes/pilots/pilots'));
app.use('/pilots/stripe', require('./routes/pilots/stripe'));
// ...
// Index page for Rocket Rides
app.get('/', (req, res) => {
res.render('index');
});
// ...
// Start the server on the correct port
const server = app.listen(process.env.PORT || config.port, () => {
console.log(' Rocket Rides server started:', config.publicDomain);
});
其次,我将本教程与以下相关代码一起使用:
// Match the raw body to content type application/json
app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
console.log("called!");
let event;
try {
event = JSON.parse(request.body);
} catch (err) {
response.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntentSucceeded = event.data.object;
break;
case 'payment_method.attached':
const paymentMethod = event.data.object;
break;
// ... handle other event types
default:
// Unexpected event type
return response.status(400).end();
}
// Return a response to acknowledge receipt of the event
response.json({received: true});
});
app.listen(8000, () => console.log('Webhooks running on port 8000'));
对于这两个部分,服务器不处理 webhook 请求:
在端口 8000 上运行的 Webhook POST /webhook 404 590.525 毫秒 - 1415
发件人收到 404。
当我注释掉第一部分的大部分代码时,webhook 请求得到了正确处理:
在端口 8000 上运行的 Webhook 叫!
发件人收到 200。
我相信来自 Web 服务器的其中一条路由正在屏蔽端点的路由。我试着用这个线程寻找一个:
app._router.stack.forEach(function(middleware){
if(middleware.route){ // routes registered directly on the app
routes.push(middleware.route);
} else if(middleware.name === 'router'){ // router middleware
middleware.handle.stack.forEach(function(handler){
route = handler.route;
route && routes.push(route);
});
}
});
console.log(routes);
唯一相关的是GET /
.
如果我在路由器代码之前包含端点代码,则 webhook 将得到正确处理。
如何找到屏蔽 webhook 端点的路由?
解决方案
将更具体的路由定义放在首位,如下所示:
app.use('/pilots/stripe', require('./routes/pilots/stripe'));
app.use('/pilots', require('./routes/pilots/pilots'));
并且,稍后更一般的路线定义。这可以确保更具体的路线不会被更通用的处理程序吞噬。
请记住,使用app.use()
, 类似的东西将匹配任何以包含您所有路线的app.use('/pilots')
路线开头的路线。因此,您要确保将./pilots
/pilots/stripe
app.use('/pilots/stripe', ...)
app.use('/pilots', ...)
另一个观察。在您的/webhook
处理程序中,您需要return
在发送错误状态之后,以便您的请求处理程序的其余部分不会继续运行。
// Match the raw body to content type application/json
app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
console.log("called!");
let event;
try {
event = JSON.parse(request.body);
} catch (err) {
response.status(400).send(`Webhook Error: ${err.message}`);
return; // <===== Add this
}
....
}
这似乎是实际条带文档中的一个错误。
如果我在路由器代码之前包含端点代码,则 webhook 将得到正确处理。
我猜你在服务器的其他地方有 bodyparser 中间件。如果该中间件位于此路由之前,则此路由将无法使用它bodyParser.raw()
并以它想要的方式获取数据,并且它将无法正常工作。这是因为无论哪个 bodyParser 中间件首先运行都会读取主体并对其进行解析,然后将其放置在中间件配置放置的任何位置。一旦主体被读取,它就会从流中消失,因此任何其他出现并尝试从流中读取主体数据的中间件都会发现流是空的。
因此,这条路线必须在任何其他可能处理 JSON 的正文解析中间件之前。
如果您提供了完整代码的链接,我们可以查看一下发生这种情况的位置。
推荐阅读
- javascript - Webpack ReferenceError:未定义要求(ReactJS)
- python - 在颜色图的颜色栏中选择数字的大小
- java - 使用 Ribbon 和 @LoadBalanced 进行动态身份验证
- ruby-on-rails - 转换为 JSON 时无法显示内部关联:没有将 Symbol 隐式转换为 Integer
- java - 错误检查 2D 数组,Battleship 游戏
- c++ - 递归地使用列表 STL 进行插入排序
- python - 具有平均趋势线的 Pandas matplotlib 箱线图
- c# - 使用包含 $0 的动态字符串替换文本时遇到问题
- java - Spring Security Token Auth Manager 自动装配
- c - 带有命令行参数的后缀表达式,分段错误?C