Creating a service handler in the application

All services are implemented as heirs from Service - functions of the rest module.

Each service must export a handler function that implements the asynchronous method this._route , in which it is necessary to register the processed methods and paths that return Promise through the functions this.addHandler. The processing function will have access to options, through which - access to data repositories, authorizations, metadata, and classes (if they are specified in the application configuration in the deploy file.json), and also gets an object with the typical name req - which is the request object of the express library . The data already 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 headersheader 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])
})

Example of implementing a service that outputs lists of objects with filters for the class_string class in the develop-and-test application. It is also convenient to study 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

Returns 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

Returns 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 details 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 , example from CRUD:

reqToData(req)
  .then(data => <util.js.>prepareUpdates(options, data, cm, req.params.id))