LoopBack:如何在代码中动态创建自定义REST端点(On The Fly)

时间:2015-03-08 22:45:27

标签: rest dynamic endpoint loopbackjs strongloop

我们正在使用LoopBack REST框架来公开我们的数据库(和业务逻辑)。我们需要允许客户在数据库(单租户和多租户)中创建可通过REST端点访问的自定义表。所有客户都需要使用相同的公共(生产)REST端点,这些端点将在多个服务器上公开。但是,只有创建它们的客户才能访问自定义表和关联的REST端点。这意味着我们无法将自定义表的模型写入光盘。我们需要能够在生产REST端点的上下文中动态创建实际的REST端点。

问题:我们如何在代码中动态创建自定义REST端点(即时)而无需将模型写入光盘上的JSON文件?

2 个答案:

答案 0 :(得分:5)

您可以在模型的JS文件中创建"remote method",这会在运行时添加API挂钩,尽管它在启动时。也就是说,我认为您可以使用相同的功能随时添加端点,而不仅仅是在启动时(尽管我从未尝试过):

内部/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'}
    }
  );
};

答案 1 :(得分:0)

我在环回中遇到了类似的问题。 我想出的解决方案是:

  1. 在我的数据库中维护一个表[id INT,modelName VARCHAR,datasource VARCHAR,modelConfig TEXT],它可以保存任何其他表的模型定义。

  2. 在环回中创建一个模型(称之为X)以在此表上提供CRUD操作。

  3. 在X中创建remoteMethod以更新app对象中的模型并附加到任何数据源。 实施片段如下:

  4. 
    
        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);
          }
        };