服务页面和端点的快速服务器

Express server for both serving pages and endpoint

我想要一个 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);
});

对于第二个,我使用 this tutorial 和以下相关代码:

// 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 请求:

Webhooks 运行 在端口 8000 上
POST /webhook 404 590.525 毫秒 - 1415

发件人收到 404。

当我注释掉第一部分的大部分代码时,webhook 请求得到了妥善处理:

Webhooks 运行 在端口 8000 上
叫!

发件人收到 200。

我认为来自 Web 服务器的其中一条路由正在屏蔽端点的路由。我试着用 this thread:

找一个
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
  }
  ....
}

这似乎是实际 stripe 文档中的错误。


If I include the code for the endpoint before the code for the router, the webhook is handled properly.

我猜你的服务器的其他地方有 bodyparser 中间件。如果那个中间件在这条路由之前,那么这条路由将无法使用它的 bodyParser.raw() 并按照它想要的方式获取数据并且它不会正常工作。这是因为无论哪个 bodyParser 中间件 运行s 首先读取正文并解析它,然后将其放置在中间件配置为放置它的任何位置。一旦主体被读取,它就会从流中消失,因此出现并尝试从流中读取主体数据的任何其他中间件都会发现流是空的。

因此,此路由必须位于任何其他可能处理 JSON.

的正文解析中间件之前

如果您为您的完整代码提供了 link,我们可以看一下这是在哪里发生的。