Node.js API 设计和路线处理

Node.js API design and route handling

我不太确定该用什么标题,但我是 Node.js 的新手。我刚刚在 GitHub 上找到了一个简洁的 REST API 项目来实现,但我不确定如何将所有 GET 和 POST 等拆分为单独的文件。

我有一个单一的 api.js 文件

function API_ROUTER(router, connection, md5) {
    var self = this;
    self.handleRoutes(router, connection, md5);
}

API_ROUTER.prototype.handleRoutes = function(router, connection, md5) {
    router.get("/", function(req, res) {
        res.json({"Message" : "Hello World !"});
    });
};

module.exports = API_ROUTER;

现在如何创建同级 other.js 并使用:

var api = require('./api.js');

// Create router.get, router.post etc. here?

but I'm not sure how I can split all GET and POST etc. to separate files.

组织路由的一种方法是为每个路由创建一个单独的对象,其中包含处理程序(由 HTTP 方法分隔)和其他所需信息,例如路径:

api/home.js

module.exports =  {
   path: '/',
   handlers: {
     'get': function(req, res) {
          res.json({"Message" : "Hello World !"});
      },
      'post': { 
        // ...
      }
      // ...
    }
}

api/other.js

module.exports =  {
   path: '/other',
   handlers: {
     'get': function(req, res) {
        res.json({"Message" : "Other !"});
      },
    // ...

然后你可以在 handleRoutes 方法中加载所有这些:

API_ROUTER.prototype.handleRoutes = function(router, connection, md5) {
   var routes = ['home', 'other'];

   routes.forEach(function(name) {
     // load the current route object (NOTE: you should use the path module for determining file path in a cross-platform manner)
     var routeObject = require('./' + name + '.js');

     var apiPath = routeObject.path;
     var handlers = routeObject.handlers;
     var methods = Object.keys(handlers);

     // assign handlers for each method
     methods.forEach(function(method) {
       router[method](apiPath, handlers[method]);
     });

   });
};

这将使用适当的信息和处理程序安装您的所有路由。 现在您可以通过使用必要的数据实例化 API_ROUTER 来调用此代码:

// initialize the api (and handle the routes internally)
var Api = new require('./api.js')(router, connection, md5);

如果您实施 RESTful API,那么您应该记住,这只是您提供数据的一种方式,您可能希望在将来更改它,从API 大多数时候只是翻译层。

通常你会根据资源拆分你的代码,处理请求的代码不会有那么多逻辑,它只会接受请求并在内部传递给你API。为此,如果您已经使用 express.js 或类似的库,那么您实际上并不需要额外的层。

在 express app.use([path,] function [, function...]) 中,已经提供了模块化代码所需的功能。对于每个资源,您将创建一个自己的 express.Router,它本身也可能安装另一个子模块。所以对于这部分你真的不需要图书馆。

图书馆什么时候有用:

  • 如果它自动将抛出的错误转换为正确的响应代码
  • 如果它包含自动为您的 API
  • 创建文档的工具
  • 如果它完全抽象了底层路由系统,以便您可以挂接到 expresshapi、... 而无需更改代码。

这里 express.js 的设置看起来像

./lib/rest/customer.js

var customerSystem = require('../customer-system');
var express = require('express');
var router = new express.Router();

router.get('/:id', function(req, res, next) {
  customerSystem.find({
    id: req.params.id
  }, function(err, customer) {
    if (err) {
      res.status( /*correct status code*/ ).send( /*depending on the api return json, xml, ....*/ )
    } else {
      res.send( /*depending on the api return json, xml, ....*/ )
    }
  })
});

router.delete('/:id', function(req, res, next) {
  customerSystem.delete({
    id: req.params.id
  }, function(err) {
    //...
  });
});


router.post('/', function(req, res, next) {
  //...
});

//save the customer id for the pass to the sub routers
router.use('/:id', function(req, res, next) {
  req.customerId = req.params.id;
  next();
});

router.use('/:id/addresses', require('./customer-address') )

module.exports = router;

./lib/rest/customer-address.js

var customerSystem = require('../customer-system');
var express = require('express');
var router = new express.Router();

router.get('/:id', function(req, res, next) {
  customerSystem.find({
    id: req.customerId
  }, function(err, customer) {
   // ...
  })
});

/* ..... */

//save the address id for the pass to the sub routers
router.use('/:id', function(req, res, next) {
  req.addressId = req.params.id;
  next();
});

router.use('/:id/addresses', require('./customer-address') )

module.exports = router;