Разработка обработчика сервиса в приложении¶
Все сервисы реализуются как наследники от Service - функции модуля rest.
Каждый сервис должен экспортировать функцию обработчика, в которой реализован асинхронный метод this._route
, в котором
необходимо зарегистрировать обрабатываемые методы и пути через функции this.addHandler
, возвращающие Promise. Функция обработки
будет иметь доступ к options
, через который доступ к репозиториям данных, авторизации, метаданным и классам (если они
указаны в конфигурации приложения в файле deploy.json), а также получит объект с типовым названием req
- являющимся
объектом request
библиотеки express.
Данные, прошедшие парсинг в объект будут находиться в req.body
.
Функция-обработчик должна вернуть Promise разрешающийся в результат обработки (для обработки в Service modules/rest/lib/interfaces/Service.js
),
обработчик выдаст его с кодом 200
и типом содержания Content-Type:application/json
.
Если в ходе обработки будет ошибка, перехваченная catch, то для ошибок связанных с контролем доступа будет возвращен ответ с текстом ошибки и с кодом 403
, а для всех остальных код ответа 500
и сообщением об ошибке Internal server error
.
Заголовок можно переопределить, для этого в ответе нужно отдать тип заголовка headers
, а объект в атрибуте data
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])
})
Пример реализации сервиса, выдающего списки объектов с фильтрами для класса class_string
есть в приложении develop-and-test
.
Также, для изучения удобно смотреть сам метод crud, находящийся по адресу 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;
Запрос без атрибутов в теле запроса
curl -X POST -u demo@local:ion-demo https://dnt.iondv.com:8888/rest/string-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"}]
А запрос с параметром атрибута равного значению в атрибуте string_text
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
вернет объекты удовлетворяющие условию:
[{"__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"}]
Пример регистрации тестового сервиса, подробнее см. Регистрация сервиса в конфигурации приложения
{
"modules": {
"rest": {
"globals": {
"di": {
"string-list": {
"module": "applications/develop-and-test/service/String-list",
"options": {
"stringClassName": "class_string@develop-and-test",
"dataRepo": "ion://dataRepo"
}
}
Для реализации обработки multipart запросов, например для запросов, содержащих файлы, можно использовать библиотеку multipart.js
(rest/backend/multipart.js
) модуля REST
. Пример реализации есть в сервисе CRUD
:
function reqToData(req) {
return multipart(req).then(data => data || req.body);
}
Этой цели также служит библиотека util.js
(rest/backend/util.js
), обеспечивающая корректность действий при работе с файлами и файловым хранилищем, пример из CRUD
:
reqToData(req)
.then(data => <util.js.>prepareUpdates(options, data, cm, req.params.id))