65.9K
CodeProject 正在变化。 阅读更多。
Home

Sails API 开发 (2/2):自定义方法、覆盖默认操作及相关

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (2投票s)

2015 年 5 月 3 日

CPOL

5分钟阅读

viewsIcon

19754

详细介绍使用 Sails 开发 API 的可能性,以及自定义自动生成的 API。

引言

本文是上一篇文章的第二部分... 但没有引用第一部分。本文可视为一篇关于为 Sails Nodejs 框架自定义 sails API 生成的文章。

参考Sails API 开发 (1/2):数据层 - 模型、连接、waterline、API - 蓝图及相关

文章涵盖内容

  • 您已通过 sails 生成了 API,并附加了模型,修改了模型。
  • 我们将学习如何使 API 符合您的需求,即自定义它,修改默认行为。

如何为您的 Sails API 添加自定义方法/逻辑

默认/影子路由

默认情况下,sails 提供以下方法,更多详情请参见此处

Sails 的当前版本附带以下 API 方法/默认蓝图操作

  • find
  • findOne
  • 创建
  • update
  • destroy
  • populate
  • 加法
  • 移除

这意味着,仅对于上述方法调用,您的 API 路由已定义(这些默认路由在蓝图框架中称为“影子路由”)。

要自定义调用上述方法时发生的情况,或验证 API 调用中的输入数据,或覆盖或禁用这些 API 端点,我们需要自定义默认操作/路由,或添加新操作。

涵盖的自定义技术

下面我们将探讨针对 sails v0.10.5 的四种自定义技术。

自定义现有 API 操作/路由

假设我们的数据库有一个 guid 主键,并且我们希望检查调用我们 API 时是否传递了 guid 参数。

如果未传递,或者我们想生成一个 guid,我们需要添加如下代码自定义。

所有影子路由/默认 API 调用实现都定义在您的 sails 文件夹 \lib\hooks\blueprints\actions (您的 sails 文件夹位于 node_modules 文件夹下)。

我们打开该目录下的 create.js 文件,在获取请求参数后,添加额外的代码。

/lib/hooks/blueprints/actions/create.js
module.exports = function createRecord (req, res) {

    var Model = actionUtil.parseModel(req);

    // Create data object (monolithic combination of all parameters)
    // Omit the blacklisted params (like JSONP callback param, etc.)
    var data = actionUtil.parseValues(req);

//Harish: 5/2/1015: customized
if(!data.guid) { data.guid = guid(); }   //guid() is a custom function to generate guid in javascript.
console.log(JSON.stringify(data));

...

create.js 的末尾,我们添加 guid 方法(guid 代码取自 http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript)。

//Harish: 5/2/2015: generate guid
function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

在进行上述更改后,每当您调用 'create' 操作时,您都会注意到您的 sails 窗口显示控制台日志,并且您的模型会接收到 guid 参数。

上面的代码是为如下模型和 API 调用编写的:

API 调用

https://:1337/monster/create?name=lkjkljlkj

/api/models/monster.js

module.exports = {

  attributes: {
      name: {
      type: 'string',
      columnName: 'name'
    },
    guid: {
      type: 'string',
      unique: true,
      primaryKey: true,
      columnName: 'guid'
    }
  }
};

覆盖现有 API 操作/路由

与上面类似,但无需修改 node_modules\sails 目录下的 sails 代码(这样您就可以稍后升级 sails,而无需重写自定义代码),您可以通过覆盖蓝图实现来进行自定义。

(如此处所示:https://stackoverflow.com/questions/22273789/crud-blueprint-overriding-in-sails-js

在项目 \api 目录下的 \blueprints 文件夹下创建一个文件,如果您想覆盖默认实现,可以创建一个类似 create.js 的文件。

提示是:----------------

您可以参考/复制上一个部分使用的默认 create.js 并进行修改。

这应该没问题,除了为了确保蓝图 ActionUtil 引用工作正常,您可能需要在 require(actionUtil) 行的替换处添加以下行。

actionUtil = require('sails/lib/hooks/blueprints/actionUtil');

-------------------

如果您的 \api\blueprints 目录只包含 create.js,sails 会智能地只覆盖 create 蓝图方法,而不覆盖其他方法。

注意

  • 不过有一个问题是,所有覆盖都适用于所有 API 控制器。因此,如果您在项目中拥有 2 个 API,例如 admin.jsuser.js,那么您将无法单独覆盖 admin.jsdestroy 方法(举个例子)。
    • 所以,如果您为某个 API 控制器覆盖了 destroy.js,那么您就为所有控制器都覆盖了它,并且可能需要编写额外的代码(请继续阅读下面的要点)。
    • 这种行为是设计使然。
      • 您可以在覆盖的代码中使用 req.options.controller / req.options.model 来决定您的覆盖如何针对不同的控制器工作。这些选项将返回调用 destroy 方法的模型/控制器。
  • 目前所有覆盖相关文件必须是小写! (默认操作包含 findOne.js,但在 /api/blueprints 中,需要是 findone.js。)

禁用现有 API 操作/路由

您可以通过在 API 的控制器中放置以下代码来禁用 API 的所有默认蓝图操作。

所以,如果您有一个 monster API,那么您将在 /api/controllers/MonsterController.js 中放置以下代码。

下面的 _config 值将覆盖 /config/blueprint.js 下的全局配置,针对您的控制器。

module.exports = {
  _config: {
    actions: false,
    shortcuts: false,
    rest: false
  }
}

上面的代码禁用了所有默认操作。大多数情况下,您不需要这样做,因为这会削弱任何自动生成 API 本身的需求。

但是,如果您想将某些 API 功能设置为安全或受保护,不被默认访问,那么下面的代码将有所帮助。

如何仅禁用部分默认方法而不全部禁用

假设您不希望您的 API 用户删除记录。

您可以通过在 /api/blueprints/destroy.js 下创建一个空的 destroy.js 文件来简单地覆盖 destroy 方法。

这将为 destroy 调用返回 404。

注意:覆盖适用于所有控制器,而不仅仅是其中一个。要控制此行为,请阅读上面“覆盖现有”部分下的“注意”部分。

添加新的 API 操作/路由

同样,您只需要在 /api/blueprints 文件夹下添加一个自定义方法。如果您添加 abc.js,那么 abc 将通过蓝图作为 API 方法加载,如“覆盖现有”部分所述。

注意:对于不是影子路由覆盖的自定义方法,您必须添加自定义路由。

这只是一个简单的配置行,可以添加到路由配置中(如 此处 所示)。

If you create a /blueprints/foo.js file, you can bind a route to it 
in your /config/routes.js file with (for example):

GET /myRoute': {blueprint: 'foo'}

侧边栏注意:在与核心贡献者就类似的自定义进行的一次有趣的讨论可以在 https://github.com/balderdashy/sails/issues/1653 上找到。

Sails 缺少文档 - 部分内容记录在 github issue 中 @ https://github.com/balderdashy/sails/issues

事实上,sails 的许多缺失文档都可以从 sails github issue 线程中学习到……例如隐藏的功能。

本文中的一些细节基于从那里收集的信息。

© . All rights reserved.