javascript - 如何使用restify.js处理深层且复杂的数据结构

标签 javascript node.js rest restify

我见过 Restify 的示例,其中所有端点都位于根目录:/users、/data 等。我知道可以像这样实现嵌套:

server.get('/users/:user/data/:id', returnData);

和 req.params 变量将包含所有请求参数。示例:

{ user: '45', id: '80' }

如果我的应用程序具有很少的端点,这似乎工作正常,但如果我有一个深层且分支的数据结构,我想通过 REST API 公开,该怎么办?类似于:

{
  stuff: {
    points: {
      colors: {
        shinyThings: {},
        dullThings: {}
      }
    },
    ships: {
      enterprises: {},
      starDestroyers: {}
    }
  },
  things: {},
}

必须手动编写所有这些端点的路径似乎并不正确。我最终得到了很多路径定义和类似这样的东西:

server.put('/stuff/:stuff/points/:points/colors/:colors/shinyThings/:shinyThings', returnShinyThing);

有没有更简单的方法可以使用 Restify 来做到这一点?

最佳答案

我已经想出了一种方法来做到这一点,尽管我确信还有更好的选择:

1) 创建模块来处理端点上的某些操作。这些模块将需要集成到中央路由器模块中。示例stuff.js :

exports.list = function(req, res, next) {
  // Code to handle a GET request to /stuff
};

exports.create = function(req, res, next) {
  // Code to handle a POST request to /stuff
};

exports.show = function(req, res, next) {
  // Code to handle a GET request to /stuff/:id
};

exports.update = function(req, res, next) {
  // Code to handle a PUT request to /stuff/:id
};

exports.destroy = function(req, res, next) {
  // Code to handle a DELETE request to /stuff/:id
};

2) 在路由器模块中定义 Action -> http 动词的映射:

var actions = {
  list: 'get',
  create: 'post',
  show: 'get',
  update: 'put',
  destroy: 'del'
}

3)创建一个表示数据结构的对象,如下所示:

var schema = {
  stuff: {
    _actions: require('./stuff'),
    points: {
      _actions: require('./points'),
      colors: {
        _actions: require('./colors'),
        shinyThings: {_actions: require('./shinyThings')},
        dullThings: {_actions: require('./dullThings')}
      }
    },
    ships: {
      _actions: require('./ships'),
      enterprises: {_actions: require('./enterprises')},
      starDestroyers: {_actions: require('./starDestroyers')}
    }
  },
  things: {_actions: require('./things')},
}

4) 在路由器初始化期间,应用程序向其传递一个 Restify 服务器对象以附加路由。在初始化期间,递归函数遍历模式对象,并且当 _actions key 发现它调用第二个函数,该函数将给定路径处的路由处理程序附加到给定的服务器对象:

(function addPathHandlers(object, path) {
  for (var key in object) {
    if (key === '_actions') addActions(object, path);
    else if (typeof object[key] === 'object') {
      var single = en.singularize(path.split('/').pop());

      if (path.charAt(path.length - 1) !== '/') {
        path += ['/:', single, '_id/'].join('');
      }

      addPathHandlers(object[key], path + key);
    }
  }
})(schema, '/');

function addActions(object, path) {
  // Actions that require a specific resource id
  var individualActions = ['show', 'update', 'destroy']; 

  for (var action in object._actions) {
    var verb = actions[action];

    if (verb) {
      var reqPath = path;
      if (individualActions.indexOf(action) !== -1) reqPath += '/:id';

      server[verb](reqPath, object._actions[action]);
    }
  }
}

注释:这利用了 lingo模块(即 en.singularize() 函数)。由于我删除了函数的非关键部分,它也得到了一些简化,但它应该具有完整的功能。

这个灵感来自于研究了express-resource 的实现方式,尽管它并不那么精致且易于使用。

关于javascript - 如何使用restify.js处理深层且复杂的数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13726718/

相关文章:

javascript - 如何在 JavaScript 中将 Object {} 转换为 Array [] 键值对

javascript - 我使用 jquery 错误地选择了对象

node.js - Sequelize 模型上的外键定义

node.js - Yeoman Web 应用程序中没有/bower_components/

rest - OSS 连结 : how to use REST API to retrieve last version as a text

javascript - Angular JS http 获取基本身份验证

javascript - Vue vee-validate 服务器端错误根本没有设置

javascript - ES6 Node.js/Express.js 模型对象的唯一主键

java - 如何通过 REST API 关联两个实体

rest - FOSRestBundle Camel 键规范化器不起作用