Click here to Skip to main content
12,689,305 members (28,308 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

8.7K views
1 bookmarked
Posted

Sails API development (2/2): Custom methods, overriding default actions, and related

, 2 May 2015 CPOL
Rate this:
Please Sign up or sign in to vote.
Documents the details on possibilities of developing API with Sails, and customizing auto-generated api.

Introduction

This article is the 2nd part of a previous article.. but is not written with contextual reference to the 1st part. This can be considered an article on customizing sails api generate, for the Sails Nodejs framework.

Reference: Sails API development (1/2): Datalayer -models, connections, waterline, API -blueprint, and related 

What is covered in the article:
You have generated api through sails, and attached models, modified the models. 
We learn about making the api fit into your requirements, namely customizing it, modifying default behaviour.

How to add Custom Methods / logic on your Sails API

Default / Shadow Routes

By default sails provides the following methods, more details here.
 
The current version of Sails ships with the following api methods / default blueprint actions:
  • find
  • findOne
  • create
  • update
  • destroy
  • populate
  • add
  • remove
That means, only for the above method calls your API routes are defined (these default routes are called 'shadow routes' on the blueprint framework.)
 
To customize what happens when the above methods are called, or to validate input data on API calls, or to override or disable these api end points, we have to customize the default actions/routes, or add new actions.
 

Customization Techniques covered

We will explore 4 customization techniques targeted for sails v0.10.5 below:

Customize existing API Action/Route

Say, our database has a guid primary key, and we want to check that the call to our API passes a guid parameter.
If not passed, or if we want to generate a guid, we need to add code customization like below.
 
All shadow route / default API call implementations, are defined under your sails folder \lib\hooks\blueprints\actions (and your sails folder is under your node_modules folder.)
 
We open the create.js under the directory, and just after getting the request parameters, we add additional code.
 
/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));

...

At the end of create.js, we add the guid method (function guid code taken from 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();
}

After the above changes, whenever you call a 'create' action, you will notice your sails window showing the console log, and your model getting the guid parameter.

The above code is written for a model and API call like below

api call:

http://localhost: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'
    }
  }
};
 

Override existing API Action/Route

In a similar way like above, but without touching sails code under your node_modules\sails directory (so that you can upgrade sails later and your customization won't have to be re-written)
you could do the customization by overriding the blueprint implementation. 
 
 
Create a \blueprints folder under your project's \api directory, and create a file like create.js if you want to override the default implementation.
 
And the hint is: ----------------
 
You could refer to / make a copy of the default create.js (as used in previous section) and modify.
 
It should be fine, except that, to ensure blueprint ActionUtil reference works, You may have to add the below line in replacement of the require(actionUtil) line
actionUtil = require('sails/lib/hooks/blueprints/actionUtil');
-------------------
 
If your \api\blueprints directory contains only create.js, sails intelligently overrides only the create blueprint method, and not the others.

NOTE:

  • One problem though, is that, all overrides are for all api controllers. So if you have 2 APIs in your project like admin.js and user.js, then there is no way you can override admin.js's destroy method alone (as an example).
    • So if you override destroy.js for one API controller, you are overriding it for all of them, and additional code may have to be written (read on to below point).
    • This behaviour is by design
      • You can use req.options.controllerreq.options.model in your overridden code, to decide how your override works for different controllers. These options will return for which model/controller is the destroy called.
  • Currently all overrides related files must be lowercase! (The default actions contains findOne.js, but in /api/blueprints it needs to be findone.js)

Disable existing API Action/Route

You could disable all default blueprint actions for your api by putting the below in your api's controller.
 
So if you had a monster api, then you would put below code in /api/controllers/MonsterController.js
The _config values below, will override global configuration under /config/blueprint.js, for your controller.
module.exports = {
  _config: {
    actions: false,
    shortcuts: false,
    rest: false
  }
}
The above disables all default actions. Mostly you won't need to do that, since that kind of handicaps necessity for any auto-generated api itself.
 
But if you want some API functionality to be secured or protected away from default, the below will help.

How to Disable only some of the default methods but not all

Suppose you do not want your api users to delete records.
You could simply override the destroy method by creating an empty destroy.js file under /api/blueprints/destroy.js
And this will return a 404 for the destroy call.
 
Note: Overrides apply for all controllers not just one of them, to control that behaviour, read the Note section under 'override existing' section above.

Add new API Action/Route

Again, all you need to do is add a custom method under /api/blueprints folder. if you add abc.js then abc is loaded as an API method through blueprint.
As mentioned in 'override existing' section above.
 
Note: For the custom methods which are NOT overrides of the shadown routes, you have to add custom routes.
This is just an easy config line to be added in routes config. (as found here)
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'}
 
Sidebar Note: There is an interesting conversation on a similar customization with the core contributors here: https://github.com/balderdashy/sails/issues/1653
 

Sails Missing documentation - some found recorded under github issues https://github.com/balderdashy/sails/issues

In fact, many of the missing documentation for sails can be learnt from the sails github issue threads...like hidden functions.
Some amount of detail on this article is based out of information consolidated from there.
 
 
 
 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Harish loves computers for their basic quality of running tasks given and doing things clockwork without day-dreaming like him.

Note: My employer does not subscribe to my thoughts posted in my articles.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170113.4 | Last Updated 3 May 2015
Article Copyright 2015 by Harish Palaniappan
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid