Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple api versions in a single loopback app #2483

Closed
vasanthps-rm opened this issue Jul 1, 2016 · 16 comments
Closed

Support multiple api versions in a single loopback app #2483

vasanthps-rm opened this issue Jul 1, 2016 · 16 comments

Comments

@vasanthps-rm
Copy link

Kindly add support to multiple api versions in a single loopback app.

For ex:-

In config.*.js, instead of

module.exports = {
  restApiRoot: "/api/v1'',
  host: process.env.HOST || 'localhost',
  port: process.env.PORT || 3000
};

We could do

module.exports = {
  baseUrl: "/api",
  restApiRoots: ["v1'', "v2"],
  defaultApiRoot: "v2",
  host: process.env.HOST || 'localhost',
  port: process.env.PORT || 3000
};

And for a model, say 'device.json', the corresponding js files can be 'device.v1.js' and 'device.v2.js', each file with api's for their respective versions. The acl's in the json file should have api versions included as well.

Suggestions and better way to implement this feature is also welcome

@superkhau
Copy link
Contributor

@vasanthps-rm Would you like to submit a PR? Sounds like a good suggestion. @bajtos @raymondfeng Thoughts?

@vasanthps-rm
Copy link
Author

@superkhau Sure. I will work on it!

@superkhau
Copy link
Contributor

@vasanthps-rm 👍 Just ping me when you're done and I'll help review it. Good luck! 🍀

@franher
Copy link

franher commented Jul 7, 2016

We are looking forward to have this feature 💪

@barocsi
Copy link

barocsi commented Aug 31, 2016

+1
But, I will be evil here, should it not be like something as a default building block of an API?

@Samox
Copy link

Samox commented Dec 21, 2016

+1

@joeybenenati
Copy link

any movement on this?

@box-as
Copy link

box-as commented Mar 5, 2017

Any update on this feature?

@ako977
Copy link

ako977 commented Apr 23, 2017

+1 on this feature.
Currently I'm hacking this by allowing a variable for the API version defined in middleware config:

"routes": {
    "loopback#rest": {
      "paths": [
        "${restApiRoot}"
      ]
    }
  }

Then explicitly looking for that variable in the remoteMethods.

@joeybenenati
Copy link

@ako977 could you please elaborate on your versioning workaround? How do you support multiple versions?

@ako977
Copy link

ako977 commented Apr 24, 2017

@joeybenenati sorry, I wasn't complete in my previous comment.

I do the following:

middleware.json:

"routes": {
    "loopback#rest": {
      "paths": [
        "${restApiRoot}"
      ]
    }
  }

In the above case, restApiRoot is the constant you define in config.json eg. restApiRoot: "/api"

Then in your model config.
<mymodel>.json:

"http": {
    "path": ":apiVersion/user"
  },

The above will give you /api/:apiVersion/user

To grab this variable, you can add a boot script to retrieve it on every API call eg.

var loopback = require('loopback');

module.exports = function(app, bootCallback) {
    // Set the values for apiVersion for all requests coming in
    app.use(function (req, res, next) {
        var matches = req.path.match(/^\/api\/(v\d+)\/.*/i);
        if (matches && matches.length > 1) {
           // this requires some sort of context plugin to provide the apiVersion across execution of this call. Loopback no longer really recommends their context plugin
            req.apiVersion = matches[1];
        }    
        next();
    });

    bootCallback();
};

In your remoteMethod definitions you can explicitly request the apiVersion as a query param eg.

User.remoteMethod (
        'passwordReset',
        {
            http: {path: '/password-reset', verb: 'post'},
            accepts: [
                {arg: 'id', type: 'integer', required: true, http: { source: 'form' }},
                {arg: 'password', type: 'string', required: true, http: { source: 'form' }},
                {
                   arg: 'version', type: 'object', description: 'API version eg. v1, v2, etc.',
                   http: function (context) {
                       return {apiVersion: context.req.apiVersion};
                   } 
                }
            ],
            returns: {arg: 'data', type: 'boolean'}
        }
    );

Incidentally, I use the above refactored into a utility function on all my remote method query param definitions. This way the utility function automatically adds the apiVersion as well as access token to all my param arguments.
Eg.

accepts: ModelManager.buildRemoteMethodArgs([
                {arg: 'id', type: 'integer', required: true, http: { source: 'form' }},
                {arg: 'password', type: 'string', required: true, http: { source: 'form' }}])

It's my solution for the context plugin bugginess observed in loopback.

You can then easily grab it in your remote method function:

User.passwordReset = function(version, id, password, cb) {
        switch ( version.apiVersion ) {
            case 'v1':
               // version specific API method
               break;
            case 'v2':
               // version specific API method
               break;
            default:
               cb(null, false);           
        }
    };

@stale stale bot added the stale label Aug 23, 2017
@stale stale bot closed this as completed Sep 6, 2017
@richard-dev-mx
Copy link

richard-dev-mx commented Jan 5, 2018

@vasanthps-rm I just only create a new property (in my case baseRestApiRoot) in config*.js like this

module.exports = { baseRestApiRoot: '/api/v1', restApiRoot: '/api/v1.0.5', host: process.env.HOST || 'localhost', port: process.env.PORT || 3000 };

and I modified the middleware.json in this way

"routes": { "loopback#rest": { "paths": [ "${baseRestApiRoot}", "${restApiRoot}" ] } }

and thats all

@Aman-Aalam
Copy link

Any update on this?
I am going to try these work around, but anything official?

@Aman-Aalam
Copy link

@rikantro Can you please explain a bit more on what's happening here?
How do you route models with requests sent to api/v1/model ?
I tried doing what you suggested and now I receive only a 404

@mrumaiz
Copy link

mrumaiz commented Jun 20, 2019

Is that feature done?

@gytisrepecka
Copy link

Curious to know if that is something planned to be implemented in Loopback v4?

Or the only option is to use conditional logic like in @ako977's comment?

It seems v3 supported adding version to REST API route, but it was just using the currently defined version of the API - still just one and only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests