【问题标题】:NodeJS Rest API - where is the right place to call external APINodeJS Rest API - 调用外部 API 的正确位置在哪里
【发布时间】: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。我不确定,如果我应该调用模型或通过控制器(或中间件?)来做。 我应该在哪里以及如何做,为什么?谢谢!

【问题讨论】:

    标签: node.js api rest express


    【解决方案1】:

    在我看来还不错。真的取决于是否需要每次请求都进行 API 调用。假设用户向您的 API 发出请求,然后向外部 API 发出请求以验证该用户,您将需要来自每个请求的身份验证令牌。

    不过,您可以更好地组织代码。例如:

    ?api

    ┣ ?控制器

    ┃ ┗ ?test.js

    ┣ ?服务

    ┃ ┗ ?EXTERNAL_API_ENDPOINT.js

    ┗ ?index.js

    api/services/EXTERNAL_API_ENDPOINT.js

    const axios = require("axios");
    
    async function getService(token) {
        return axios.get(EXTERNAL_API_ENDPOINT, {
            headers: { cookie: `token=${token}` }
        });
    }
    module.exports = getService;
    

    api/controllers/test.js

    const getService = require("../services/EXTERNAL_API_ENDPOINT");
    
    async function test(req, res, next) {
        const token = req.headers.token;
        const respond = await getService(token)
    }
    module.exports = test;
    

    api/index.js

    const test = require("./controllers/test");
    
    app.get('/api/v1/test',  test);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-24
      相关资源
      最近更新 更多