Нello!我希望调用已传递给expressRouter.post(...)
调用的函数。
此expressRouter.post(...)
调用发生在我我无法修改的文件中。该代码已经分发给许多客户端,并且没有任何程序可以修改它们的文件版本。虽然 I 无法为远程客户端更新此文件,但其他开发人员却可以。因此,我面临着将来该POST端点的行为发生变化的问题。
我也在处理性能问题。该POST端点期望req.body
是已解析的JSON对象,并且该JSON对象可能过大。
我的目标是编写一个GET端点,该端点在内部激活该POST端点。 GET端点将需要使用非常大的JSON值调用POST端点,该JSON值已插入URL查询参数。 GET的功能应始终反映POST的功能,包括将来是否更新POST的功能。因此,我无法复制/粘贴POST的逻辑。还要注意,JSON格式永远不会改变。
我了解,通常通过1){extracting the router function into an accessible scope或2)generating an HTTP request to localhost解决了内部调用expressjs端点的问题。
不幸的是,在我看来,这些选项都不可行:
这是我的(人为)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:<port>/my/post/endpoint
发出POST请求,则会根据是否在JSON正文中包含“ val”而得到预期的错误或响应。
现在,我希望具有完全相同的可用功能,但要通过GET,并在URL中而不是任何JSON正文中提供“ val”。我尝试了以下操作:
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请求?
答案 0 :(得分:1)
一个简单的中间件怎么样?
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函数用作Express处理程序,带有请求,响应和下一个。首先检查参数,然后检查身体。
答案 1 :(得分:1)
这似乎可行,但是修改req
并传递它而不是创建一个全新的fakeReq
对象可能更有意义。启用此功能的是router.handle(req, 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, () => {});
};