Adding a Controller Route
Kuzzle's API is divided into separate "controllers", each exposing executable "actions" (see API reference).
Plugins allow you to install additional controllers that will be available through Kuzzle's API, each with their own list of available actions.
Controller Route Path
To avoid naming conflicts, the path to the controller added using a plugin will include the plugin name.
HTTP
URL: http://<server>:<port>/_plugin/<plugin name>/<url defined by the plugin>/<resources>
Method: <verb defined by the plugin>
Others protocols
{
"controller": "<plugin name>/<added controller name>",
"action": "<action of the added controller>",
...
}
Creating a Controller Route
In order to create a new controller, the plugin must expose the following objects:
- A
controllers
object, describing the new controller(s) to add. It will automatically be made available to any network protocol (except for HTTP) - A
routes
objects, describing how the new controller(s) should be exposed to the HTTP protocol. Only GET and POST verbs are accepted. - Controller's actions functions. These methods take a
Request
object as an argument, and must return aPromise
that resolves with the action result or rejects with a KuzzleError object.
From Request to Action
All action functions receive a Request object as a main argument. When Kuzzle receives a request, it will parse the data and create the Request object that it then passes to the action. The parsing works as follows:
HTTP:
- dynamic arguments provided in the URL, headers and query string arguments are stored in
request.input.args
- content body is made available in
request.input.body
- if the URL contains an
index
, acollection
or a_id
argument, it will be stored inrequest.input.resource
- dynamic arguments provided in the URL, headers and query string arguments are stored in
Other protocols:
- if the provided JSON object contains a
body
object, then its content will be stored inrequest.input.body
- the following fields at the root of the provided JSON objects are available in
request.input.resource
:index
,collection
,_id
- any unrecognized property at the root of the provided JSON object will be stored in the
request.input.args
part of theRequest
object
- if the provided JSON object contains a
Automatic Events Generation
Kuzzle can trigger events on all controller routes, and those added by plugins are no exception.
Read more about these automatic controller events here.
Plugin Sample
class ControllerPlugin {
constructor () {
/*
This exposed "controllers" property tells Kuzzle that it needs to extend
its API with new controllers and actions.
Here, we add a controller "newController", with 2 described actions:
"myAction" and "myOtherAction".
These actions point to functions exposed to Kuzzle by the plugin.
Any network protocol other than HTTP will be able to invoke this new
controller with the following JSON object:
{
controller: '<plugin name>/newController',
action: 'myAction',
...
}
*/
this.controllers = {
newController: {
myAction: 'actionFunction',
myOtherAction: 'otherActionFunction'
}
};
/*
We also want to expose our new controller to the HTTP protocol.
To do so, we give Kuzzle instructions on how we want to expose our
controller to HTTP.
Any parameter starting with a ':' in the URL will be made dynamic by Kuzzle.
The first route exposes the following GET URL:
http://<kuzzle server>:<port>/_plugin/<plugin name>/foo/<dynamic value>
Kuzzle will call the function 'actionFunction' with a Request object,
containing the "name" property: request.input.args.name = '<dynamic value>'
The second route exposes the following POST URL:
http://<kuzzle server>:<port>/_plugin/<plugin name>/bar
Kuzzle will provide the content body of the request in the Request object
passed to the function 'otherActionFunction', in the request.input.body
property
*/
this.routes = [
{verb: 'get', url: '/foo/:name', controller: 'newController', action: 'myAction'},
{verb: 'post', url: '/bar', controller: 'newController', action: 'myOtherAction'}
];
}
/*
Required plugin initialization function
(see the "Plugin prerequisites" section)
*/
init (customConfig, context) {
// plugin initialization
}
/*
Implements the action newController/myAction
Takes a Request object as an argument, and MUST return
a promise resolved (or rejected) with the action's result
This result can be of any JS type (scalar, object, array), and
will be used to build a response to send to the requesting client
See the "How plugins receive action arguments" chapter just below
for more information.
*/
actionFunction (request) {
// do action
// optional: set network specific headers
if (request.context.protocol === 'http') {
// expires in 1h
request.response.setHeader('expires', new Date(Date.now() + 3600000).toUTCString());
}
// Resolve with the result content. For instance:
return Promise.resolve({acknowledge: true});
}
/*
Implements the action newController/myOtherAction
Takes a Request object as an argument, and MUST return
a promise resolved (or rejected) with the action's result
This result can be of any JS type (scalar, object, array), and
will be used to build a response to send to the requesting client
See the "How plugins receive action arguments" chapter just below
for more information.
*/
otherActionFunction (request) {
// do action
return Promise.resolve(/* result content */);
}
}
// Exports the plugin objects, allowing Kuzzle to instantiate it
module.exports = ControllerPlugin;