Node.js 手动呼叫快速路由器

Node.js 手动呼叫快速路由器,node.js,performance,express,Node.js,Performance,Express,你好!我想调用一个已经传递给expressRouter的函数。。。打电话 这是expressRouter.post。。。调用发生在我无法修改的文件中。代码已经分发给许多客户机,我没有任何过程来修改他们的文件版本。虽然我无法为远程客户端更新此文件,但其他开发人员可以。因此,我面临着这个后端点的行为在未来发生变化的问题 我也在处理性能问题。此POST端点期望req.body是一个已解析的JSON对象,并且该JSON对象可能过大 我的目标是编写一个GET端点,在内部激活这个POST端点。GET端点将需

你好!我想调用一个已经传递给expressRouter的函数。。。打电话

这是expressRouter.post。。。调用发生在我无法修改的文件中。代码已经分发给许多客户机,我没有任何过程来修改他们的文件版本。虽然我无法为远程客户端更新此文件,但其他开发人员可以。因此,我面临着这个后端点的行为在未来发生变化的问题

我也在处理性能问题。此POST端点期望req.body是一个已解析的JSON对象,并且该JSON对象可能过大

我的目标是编写一个GET端点,在内部激活这个POST端点。GET端点将需要使用非常大的JSON值调用POST端点,其中插入了URL查询参数。GET的功能应该始终镜像帖子的功能,包括帖子的功能是否在将来更新。因此,我无法复制/粘贴帖子的逻辑。还要注意,JSON格式永远不会改变

我知道,在内部调用expressjs端点的问题通常由1或2解决

不幸的是,在我的情况下,这两种选择都不可行:

我不能将函数移动到可访问的范围内,因为我不能修改源代码,也不能复制粘贴函数,因为原始版本可能会更改 出于性能考虑,避免HTTP请求是一个高优先级问题。HTTP请求将需要序列化+反序列化一个过大的JSON主体,重新访问许多身份验证中间件,这些中间件需要等待进一步的HTTP请求+数据库查询完成,等等 以下是我精心设计的POST端点:

expressRouter.post('/my/post/endpoint', (req, res) => {

  if (!req.body.hasOwnProperty('val'))
    return res.status(400).send('Missing "val"');

  return res.status(200).send(`Your val: ${req.body.val}`);

});
如果我向localhost:/my/POST/endpoint发出POST请求,我将根据JSON正文中是否包含val获得预期的错误或响应

现在,我希望有完全相同的功能可用,但通过GET,并在URL中提供val,而不是在任何JSON正文中。我尝试了以下几点:

expressRouter.get('/my/get/endpoint/:val', (req, res) => {

  // Make it seem as if "val" occurred inside the JSON body
  let fakeReq = {
    body: {
      val: req.params.val
    }
  };

  // Now call the POST endpoint
  // Pass the fake request, and the real response
  // This should enable the POST endpoint to write data to the
  // response, and it will seem like THIS endpoint wrote to the
  // response.
  manuallyCallExpressEndpoint(expressRouter, 'POST', '/my/post/endpoint', fakeReq, res);

});
不幸的是,我不知道如何实现manuallyCallExpressEndpoint


这个问题有没有一个解决方案,既不将函数提取到一个可访问的范围,也不生成一个HTTP请求?

一个简单的中间件怎么样

function checkVal(req, res, next) {
  const val = req.params.val || req.body.val

  if (!val) {
    return res.status(400).send('Missing "val"'); 
  }

  return res.status(200).send(`Your val: ${val}`);
}

app.get('/my/get/endpoint/:val', checkVal)
app.post('/my/post/endpoint', checkVal)
这段代码没有经过测试,但让您大致了解如何在这两个地方运行相同的代码


checkVal函数充当一个快速处理程序,包含请求、响应和下一步。它首先检查参数,然后检查主体。

这似乎是可能的,但修改req并传递它可能更有意义,而不是创建一个全新的fakeReq对象。启用此功能的东西看起来是router.handlereq,res,next函数。我不确定这是最明智的方法,但它肯定会避免单独http请求的巨大开销

app.get('/my/get/endpoint/:val', (req, res) => {

  // Modify `req`, don't create a whole new `fakeReq`
  req.body = {
    val: req.params.val
  };

  manuallyCallExpressEndpoint(app, 'POST', '/my/post/endpoint', req, res);

});

let manuallyCallExpressEndpoint = (router, method, url, req, res) => {
  req.method = method;
  req.url = url;
  router.handle(req, res, () => {});
};

你是否考虑过这个问题???假装我无法访问它所定义的文件-为什么?如果它是同一个应用程序的一部分,那么提取相关的业务层方法并直接调用它是迄今为止实现这一点的最简单和最有效的方法。是的-需要“http”。get将生成一个http请求,这是我想要避免的。有几个原因;首先,它需要我序列化/反序列化我的JSON正文,这是不必要的。我还不确定你的方法的目标是什么……好吧,停止追求错误的选项。您不应该仅仅因为某段代码的某个顽固的维护者而避免使用正确的编码方式。您应该能够很好地表明,您的修改不会以任何方式更改上一个路由的结果,同时允许您高效地重用其部分代码用于其他有用的目的。不幸的是,这需要我更改传递给app.post的函数。。。我想避免。我理解,我不确定你能实现你想要的。您希望在两个不同的位置执行同一段代码,而无需将其包装在函数中或进行http调用。对吗?@GershomMaes你无论如何都得修改代码@是的,没错!该函数必须位于内存中的某个位置。出于可维护性的原因,我不想复制/粘贴它,并且由于问题的限制,我不想修改应用程序。发布。。。代码。@MarceloFilho如果你看我的答案,看起来解决方案是可能的,不需要更改代码!