【发布时间】:2022-01-21 16:25:15
【问题描述】:
我在 Node.JS 中编写 Rest API,它使用 MySQL 数据库但也使用外部 API,我需要在其中获取一些数据。
我正在使用 Express 和“路由器、中间件、控制器、模型”架构,但我不确定调用外部 API 的正确解决方案是什么。在每个请求中,我都会发送外部 API 所需的令牌。我展示了我现在所拥有的并尝试描述我目前所面临的问题(请阅读代码中的 cmets。)
(另外,如果你有一些文章或教程描述了如何在使用路由器、中间件、控制器、模型架构的节点中正确编写 Rest API,请告诉我)
这是主要的 index.js
const express = require("express");
const dotenv = require('dotenv');
const cors = require("cors");
const HttpException = require('./utils/HttpException.utils');
const errorMiddleware = require('./middleware/error.middleware');
const userRouter = require('./routes/user.route');
const axios = require("axios");
// Init express
const app = express();
// Init environment
dotenv.config();
// parse requests of content-type: application/json
// parses incoming requests with JSON payloads
app.use(express.json());
// enabling cors for all requests by using cors middleware
app.use(cors());
// Enable pre-flight
app.options("*", cors());
const port = Number(process.env.PORT || 3331);
app.use(`/api/v1/users`, userRouter);
// This is an solution that works but I thinks is and nasty way how to do it
// You can see here how I need to call external API
app.get('/api/v1/test', (req, res, next) => {
const token = req.headers.token;
const respond = await axios.get(EXTERNAL_API_ENDPOINT, {
headers: {
cookie: `token=${token}`
}
});
});
// 404 error
app.all('*', (req, res, next) => {
const err = new HttpException(404, 'Endpoint Not Found');
next(err);
});
// Error middleware
app.use(errorMiddleware);
// starting the server
app.listen(port, () =>
console.log(`Server running on port ${port}!`));
module.exports = app;
user.route.js
const express = require('express');
const router = express.Router();
const userModel = require('../models/user.model');
const awaitHandlerFactory = require('../middleware/awaitHandlerFactory.middleware');
router.get('/currentUser', awaitHandlerFactory(userModel.getCurrentUser));
router.get('/logout');
module.exports = router;
我还有一个 Auth 中间件来检查令牌验证,我需要调用外部 API 来验证用户。
Auth.middleware.js
const HttpException = require('../utils/HttpException.utils');
const UserModel = require('../models/user.model');
const dotenv = require('dotenv');
dotenv.config();
const auth = (roles) => {
return async function (req, res, next) {
try {
const token = req.headers.token;
if (!token) {
throw new HttpException(401, 'Access denied. No credentials sent!');
}
/* here I need call the external API and think that I should call it from
UserModal?, but I can't because Modal doesn't have req (should I sent it
in function parmas? like this?)*/
const user = await UserModel.getCurrentUser(token, params);
if (!user) {
throw new HttpException(401, 'Authentication failed!');
}
if(!user.active || user.active !== 'Y'){
throw new HttpException(401, `User ${user.userName} is not active!`);
}
// if the user role don't have the permission to do this action.
// the user will get this error
if (roles.length && !roles.includes(user.role)) {
throw new HttpException(401, 'Unauthorized');
}
// if the user has permissions
req.currentUser = user;
next();
} catch (e) {
e.status = 401;
next(e);
}
}
}
module.exports = auth;
我不确定如何处理这个问题。我必须提供令牌和一些数据来调用外部 API。我不确定,如果我应该调用模型或通过控制器(或中间件?)来做。 我应该在哪里以及如何做,为什么?谢谢!
【问题讨论】: