如何组合两个中间件并作为一个导出?
How to combine two middleware and export as one?
我有一个实用程序文件,它基本上具有两个功能(一个用于检测用户位置,另一个用于获取用户设备详细信息)作为中间件。现在我想知道是否可以将这两个中间件组合在一起,以便它可以与路由上的其他中间件一起使用。我也希望在需要时可以自由地单独使用实用程序文件中的函数。
实用程序文件
const axios = require("axios");
const requestIp = require("request-ip");
const getDeviceLocation = async (req, res, next) => {
try {
// ToDO: Check if it works on production
const clientIp = requestIp.getClientIp(req);
const ipToCheck = clientIp === "::1" || "127.0.0.1" ? "" : clientIp;
const details = await axios.get("https://geoip-db.com/json/" + ipToCheck);
// Attach returned results to the request body
req.body.country = details.data.country_name;
req.body.state = details.data.state;
req.body.city = details.data.city;
// Run next middleware
next();
}
catch(error) {
return res.status(500).json({ message: "ERROR_OCCURRED" });
}
};
const getDeviceClient = async (req, res, next) => {
const userAgent = req.headers["user-agent"];
console.log("Device UA: " + userAgent);
next();
};
module.exports = { getDeviceLocation, getDeviceClient };
示例路线
app.post("/v1/register", [getDeviceLocation, getDeviceClient, Otp.verify], User.create);
app.post("/v1/auth/google", [getDeviceLocation, getDeviceClient, Auth.verifyGoogleIdToken], Auth.useGoogle);
我想将 getDeviceLocation
和 getDeviceClient
合并为一个 getDeviceInfo
但在需要时可以自由地单独使用 getDeviceLocation
和 getDeviceClient
在任何路线上。
使用连接节点模块,您可以组合中间件并为其公开一个新的端点。在此处参考示例代码 https://blog.budiharso.info/2015/07/28/Combine-multiple-express-middleware/
在你的情况下,也许你可以使用像这样简单的东西
const getDeviceInfo = async (req, res, next) => {
await getDeviceClient(req, res, async () => {
await getDeviceLocation(req, res, next)
})
}
但您可能需要处理错误情况。
如果你想避免回调地狱,你可以使用这样的东西:
const nextInterceptor = error => {
if (error) { throw error; }
};
const combineMiddlewares = middlewares => (req, res, next) => (
middlewares.reduce((previousMiddleware, currentMiddleware) => (
previousMiddleware.then(() => currentMiddleware(req, res, nextInterceptor))
), Promise.resolve())
.then(() => next())
.catch(next)
);
const commonMiddlewares = combineMiddlewares([getDeviceLocation, getDeviceClient]);
app.post("/v1/register", [commonMiddlewares, Otp.verify], User.create);
app.post("/v1/auth/google", [commonMiddlewares, Auth.verifyGoogleIdToken], Auth.useGoogle);
Express 允许您 declare middleware in an array,因此您可以简单地定义一组您想要组合的中间件:
const getDeviceLocation = async (req, res, next) => {
...
};
const getDeviceClient = async (req, res, next) => {
...
};
const getDeviceInfo = [getDeviceLocation, getDeviceClient];
module.exports = { getDeviceLocation, getDeviceClient, getDeviceInfo };
您可以随心所欲地使用一个或两个中间件的任意组合:
app.use('/foo', getDeviceLocation, () => {});
app.use('/bar', getDeviceClient, () => {});
app.use('/baz', getDeviceInfo, () => {});
它很简单,不需要安装任何东西。只需使用:
const {Router} = require('express')
const combinedMiddleware = Router().use([middleware1, middleware2, middleware3])
现在您可以在必要时使用组合中间件。例如:
app.get('/some-route', (req, res, next) => {
req.query.someParam === 'someValue'
? combinedMiddleware1(req, res, next)
: combinedMiddleware2(req, res, next)
})
我有一个实用程序文件,它基本上具有两个功能(一个用于检测用户位置,另一个用于获取用户设备详细信息)作为中间件。现在我想知道是否可以将这两个中间件组合在一起,以便它可以与路由上的其他中间件一起使用。我也希望在需要时可以自由地单独使用实用程序文件中的函数。
实用程序文件
const axios = require("axios");
const requestIp = require("request-ip");
const getDeviceLocation = async (req, res, next) => {
try {
// ToDO: Check if it works on production
const clientIp = requestIp.getClientIp(req);
const ipToCheck = clientIp === "::1" || "127.0.0.1" ? "" : clientIp;
const details = await axios.get("https://geoip-db.com/json/" + ipToCheck);
// Attach returned results to the request body
req.body.country = details.data.country_name;
req.body.state = details.data.state;
req.body.city = details.data.city;
// Run next middleware
next();
}
catch(error) {
return res.status(500).json({ message: "ERROR_OCCURRED" });
}
};
const getDeviceClient = async (req, res, next) => {
const userAgent = req.headers["user-agent"];
console.log("Device UA: " + userAgent);
next();
};
module.exports = { getDeviceLocation, getDeviceClient };
示例路线
app.post("/v1/register", [getDeviceLocation, getDeviceClient, Otp.verify], User.create);
app.post("/v1/auth/google", [getDeviceLocation, getDeviceClient, Auth.verifyGoogleIdToken], Auth.useGoogle);
我想将 getDeviceLocation
和 getDeviceClient
合并为一个 getDeviceInfo
但在需要时可以自由地单独使用 getDeviceLocation
和 getDeviceClient
在任何路线上。
使用连接节点模块,您可以组合中间件并为其公开一个新的端点。在此处参考示例代码 https://blog.budiharso.info/2015/07/28/Combine-multiple-express-middleware/
在你的情况下,也许你可以使用像这样简单的东西
const getDeviceInfo = async (req, res, next) => {
await getDeviceClient(req, res, async () => {
await getDeviceLocation(req, res, next)
})
}
但您可能需要处理错误情况。
如果你想避免回调地狱,你可以使用这样的东西:
const nextInterceptor = error => {
if (error) { throw error; }
};
const combineMiddlewares = middlewares => (req, res, next) => (
middlewares.reduce((previousMiddleware, currentMiddleware) => (
previousMiddleware.then(() => currentMiddleware(req, res, nextInterceptor))
), Promise.resolve())
.then(() => next())
.catch(next)
);
const commonMiddlewares = combineMiddlewares([getDeviceLocation, getDeviceClient]);
app.post("/v1/register", [commonMiddlewares, Otp.verify], User.create);
app.post("/v1/auth/google", [commonMiddlewares, Auth.verifyGoogleIdToken], Auth.useGoogle);
Express 允许您 declare middleware in an array,因此您可以简单地定义一组您想要组合的中间件:
const getDeviceLocation = async (req, res, next) => {
...
};
const getDeviceClient = async (req, res, next) => {
...
};
const getDeviceInfo = [getDeviceLocation, getDeviceClient];
module.exports = { getDeviceLocation, getDeviceClient, getDeviceInfo };
您可以随心所欲地使用一个或两个中间件的任意组合:
app.use('/foo', getDeviceLocation, () => {});
app.use('/bar', getDeviceClient, () => {});
app.use('/baz', getDeviceInfo, () => {});
它很简单,不需要安装任何东西。只需使用:
const {Router} = require('express')
const combinedMiddleware = Router().use([middleware1, middleware2, middleware3])
现在您可以在必要时使用组合中间件。例如:
app.get('/some-route', (req, res, next) => {
req.query.someParam === 'someValue'
? combinedMiddleware1(req, res, next)
: combinedMiddleware2(req, res, next)
})