LoopBack: How to Dynamically Create Custom REST Endpoints In Code (On The Fly)

你离开我真会死。 提交于 2019-12-10 10:55:18

问题


We are using the LoopBack REST framework to expose our database (and business logic). We need to allow our customers to create custom tables in the database (single and multi-tenant) which can be accessed via a REST endpoint. All customers need to use the same common (production) REST endpoints which will be on exposed on multiple servers. However, custom tables and associated REST endpoints need to be accessible to only the customers that created them. Which means we cannot write the model for custom tables to disc. We need to be able to create an actual REST endpoint on the fly within the context of our production REST endpoints.

Question: How can we dynamically create custom REST endpoints in-code (on the fly) without writing the model to a JSON file on-disc?


回答1:


You can create a "remote method" within a model's JS file, this adds the API hook "at runtime", although it is at startup. That said, I think you could use the same functions to add the endpoint any time, not just at startup (although I've never tried):

Inside /common/models/MyModel.js

module.exports = function(MyModel){

  // This is the endpoint for creating endpoints...
  MyModel.addEndpoint = function(name, method, cb) {
    // audit name and method...

    MyModel[name] = function(options, newCb) {
      // do whatever this endpoint should do...
      newCb(null, 'New endpoint success!');
    };

    MyModel.remoteMethod(
      name, 
      {
        accepts: [{arg: 'options', type: 'object'}], // or whatever you need...
        returns: {arg: 'message', type: 'string'}, // whatever it returns...
        http: {verb: method}
      }
    );

    cb(null, 'Success creating new endpoint!');
  };

  MyModel.remoteMethod(
    'addEndpoint', 
    {
      accepts: [
        {arg: 'name', type: 'string', http: {source: 'body'}},
        {arg: 'method', type: 'string', http: {source: 'body'}}
      ],
      returns: {arg: 'message', type: 'string'},
      http: {verb: 'post'}
    }
  );
};



回答2:


I have been facing a similar problem in loopback. The solution I came up with was:

  1. Maintain a table [id INT, modelName VARCHAR, datasource VARCHAR, modelConfig TEXT] in my database which could hold the model definition of any other table.

  2. Create a model (call it X) in loopback to provide CRUD operations on this table.

  3. Create remoteMethod in X to update models in the app object and attach to any datasource. The implementation snippets are as follows:

    X.updateModel = (modelName, cb) => {
      let app = X.app;
      if (modelName) {
        X.find({
          where: {
            name: modelName
          }
        }, function(err, result) {
          result.forEach(row => {
            let {
              datasource,
              modelConfig
            } = row;
            // Create a new model
            createAndAttachModel(app, datasource, JSON.parse(modelConfig));
          });
        });
        cb(null, "Created :" + modelName);
      }
    };
  X.remoteMethod('updateModel', {
    accepts: {arg: 'name', type: 'string'},
    returns: {arg: 'result', type: 'string'},
    http: {verb: 'get'},
  });
    let createAndAttachModel = (app, datasource, model) => {
      var loopback = require("loopback");
      try {
        // Create a new model object using the model incoming from the database
        let newModel = loopback.createModel(model);
        // Attach the model to an existing datasource
        app.model(newModel, {
          dataSource: null,
          public: true
        });
        let currDataSource = app.datasources[datasource];
        if (currDataSource) {
          newModel.attachTo(currDataSource);
        } else {
          console.error(datasource, "is not initialized");
        }
      } catch (error) {
        console.error(error);
      }
    };


来源:https://stackoverflow.com/questions/28932828/loopback-how-to-dynamically-create-custom-rest-endpoints-in-code-on-the-fly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!