Sails API 开发 (2/2):自定义方法、覆盖默认操作及相关
详细介绍使用 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.js 和 user.js,那么您将无法单独覆盖 admin.js 的
destroy
方法(举个例子)。- 所以,如果您为某个 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 线程中学习到……例如隐藏的功能。
本文中的一些细节基于从那里收集的信息。