Creating a service handler in the application¶
All services are implemented as heirs from Service - the functions of the rest module.
Each service has to export the handler function where the asynchronous method this._route
is implemented, in which the processed methods and paths through the functions this.addHandler
returning Promise must be registered. The processing function will get access to options
and to the data repositories, authorization, metadata and classes through it (if they are specified in the deploy.json configuration file of the application). And also the processing function will get an object with a typical name req
which is the request
object of the library express. The data parsed to the object will be located in req.body
.
The handler function must return a Promise that resolves to the processing result (for processing in Service modules/rest/lib/interfaces/Service.js
), the handler will output it with the code 200
and the content type Content-Type:application/json
. If during processing there is an error caught by catch, then for errors related to access control, a response will be returned with the error text and with the code 403
, and for all others, the response code is 500
and the error message Internal server error
.
The header can be redefined, for this, in the response you need to give the headers
header type and the object in the data
attribute
Promise.resolve({headers: ['Content-Type: image/png', 'Content-Length: 107'],
data: Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49,
0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00,
0x1F, 0x15, 0xC4, 0x89, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4B, 0x47, 0x44, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0xA0, 0xBD, 0xA7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00,
0x2E, 0x23, 0x00, 0x00, 0x2E, 0x23, 0x01, 0x78, 0xA5, 0x3F, 0x76, 0x00, 0x00, 0x00, 0x0B, 0x49,
0x44, 0x41, 0x54, 0x08, 0xD7, 0x63, 0x60, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x01, 0xE2, 0x26,
0x05, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82])
})
An example of the implementation of a service that produces lists of objects with filters for the class class_string
is in the application develop-and-test
. Пример реализации сервиса, выдающего списки объектов с фильтрами для класса class_string
есть в приложении develop-and-test
. Also, for the study, it is convenient to look at the crud method itself, located at modules/rest/lib/impl/crud.js
const Service = require('modules/rest/lib/interfaces/Service');
/**
* @param {{dataRepo: DataRepository, echoClassName: String}} options
* @constructor
*/
function listClassString(options) {
/**
* @param {Request} req
* @returns {Promise}
* @private
*/
this._route = function(router) {
this.addHandler(router, '/', 'POST', (req) => {
return new Promise(function (resolve, reject) {
try {
let filter = [];
if (req.body.string_text)
filter.push({string_text: {$eq: req.body.string_text}});
if (req.body.string_miltilinetext)
filter.push({string_miltilinetext: {$eq: req.body.string_miltilinetext}});
if (filter.length === 0)
filter = {};
else if (filter.length === 1)
filter = filter[0];
else
filter = {$and: filter};
options.dataRepo.getList(options.stringClassName, {filter: filter}).then(function (results) {
let items = [];
for (let i = 0; i < results.length; i++) {
const props = results[i].getProperties();
const item = {};
for (let p in props) {
if (props.hasOwnProperty(p))
item[props[p].getName()] = props[p].getValue();
}
items.push(item);
}
resolve({data: items});
});
} catch (err) {
reject(err);
}
});
});
}
}
listClassString.prototype = new Service();
module.exports = listClassString;
Request without attributes in the request body
curl -X POST -u demo@local:ion-demo https://dnt.iondv.com:8888/rest/string-list
will return the entire list:
[{"__class":"class_string@develop-and-test",
"__classTitle":"Class \"String [0]\"",
"id":"4567a830-b8ea-11e9-9cdf-7bd384cbb7a5",
"string_text":"example1",
"string_miltilinetext":"example1",
"string_formattext":"<p>example1</p>"},
{"__class":"class_string@develop-and-test",
"__classTitle":"Class \"String [0]\"",
"id":"4a80bdc0-b8ea-11e9-9cdf-7bd384cbb7a5",
"string_text":"example1",
"string_miltilinetext":"example2",
"string_formattext":"<p>example2</p>"},
{"__class":"class_string@develop-and-test",
"__classTitle":"Class \"String [0]\"",
"id":"66dbb3d0-5583-11e6-aef7-cf50314f026b",
"string_text":"Example of the \"String [0]\" type in the \"Text [1]\" view",
"string_miltilinetext":"Example of the \"String [0]\"\r\n in the Multiline text [7] view",
"string_formattext":"Example of the \r\n \"String [0]\" type \r\n in the \r\nFormatted text [7] view"}]
A request with an attribute parameter equal to the value in the string_text attribute Example of the \"String [0]\" type in the \"Text [1]\" view
curl -X POST -d "string_text=Example of the \"String [0]\" type in the \"Text [1]\"" \
-u demo@local:ion-demo https://dnt.iondv.com:8888/rest/string-list
will return objects that meet the condition:
[{"__class":"class_string@develop-and-test",
"__classTitle":"Class \"String [0]\"",
"id":"66dbb3d0-5583-11e6-aef7-cf50314f026b",
"string_text":"Example of the \"String [0]\" type in the \"Text [1]\" view",
"string_miltilinetext":"Example of the \"String [0]\"\r\n in the Multiline text [7] view",
"string_formattext":"Example of the \r\n \"String [0]\" type \r\n in the \r\nFormatted text [7] view"}]
An example of registering a test service, for more detailes, see Registering a service in the application configuration
{
"modules": {
"rest": {
"globals": {
"di": {
"string-list": {
"module": "applications/develop-and-test/service/String-list",
"options": {
"stringClassName": "class_string@develop-and-test",
"dataRepo": "ion://dataRepo"
}
}
To implement multipart query processing, for example, for queries containing files, you can use the library multipart.js
(rest/backend/multipart.js
) of the REST
module. There is an example of implementation in the CRUD
service:
function reqToData(req) {
return multipart(req).then(data => data || req.body);
}
The library util.js
(rest/backend/util.js
), which ensures correct actions when working with files and file storage, also serves this purpose , an example from CRUD
:
reqToData(req)
.then(data => <util.js.>prepareUpdates(options, data, cm, req.params.id))