Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maintain multiple versions of an API Rest

I have a API Rest made with Express, this is consumed by a iOS client. sometimes I have to make changes to some endpoints (Breaking Changes), I'll release a new built of the iOS App but may happens not all users update the client event if the client is running the application and I deploy the new backend version.

  1. How to maintain multiple versions of the backend?
  2. What is a good way to do this without have complex rules in the code
  3. In case that I execute different multiples instances of the base and response to each client with the correct version, now to deal with the database?

How @MikeBrant propouse I'll reduce the scope

I'm using

  • Node
  • Express
  • Postgres

I'm not using a framework like sailjs or loopback

like image 952
rkmax Avatar asked Jun 16 '15 15:06

rkmax


1 Answers

First things first, REST is for consuming resources and one could argue that you use it precisely to decouple it from backend implementation (which means it doesnt care which database, framework, ... you use).

Second, if you realy have complete implementation for first version, then it should be frozen, which in regard means don't touch backend implementation for that versin, copy routes and change them accordingly.

IMHO (what i would do):

  1. Write test for first version so you don't break something (mandatory)
  2. Prefix your urls with REST version (like everyone else, nothing new here), e.g.: api/v1/... or something like that
  3. Since you are using express you can always prefix your routes with some variable, lets say apiPath ('api/v1' for first, 'api/v2'), so you end up with something like app.delete(apiPath + '/photos/:id')

Now this is where it starts to get tricky and thats domain of your problem. If it's only model domain (new data that can be saved/retrieved) than this is easy. Suplement models with getters/setters that use attributes depending on API version. Lets say you use moongose: `

userSchema.virtual('v1_properties').get(function() {
    return ['email', 'name'];
});
userSchema.virtual('v2_properties').get(function() {
    return ['email', 'name', 'surname'];
});
modelSchema.virtual('attributes').get(function() {
    // atributes that are prefixed with api version
    var self = this;
    var json = {};
    self[apiVersion + '_properties'].foreach(function(key) {
        json[key] = self[key];
    });

    return json;
});

` For setters you do same thing. Of course it's a bad idea to couple API version with models, this is only for example purposes.

Unfortunately, this doesn't fix problem if you changed specific business logic. Remember, there is deprecation for a reason. If your changes realy broke something in older API then i presume there are only 2 options, deprecation of first API or migration of data when users do finaly update their apps. In case they use different app versions for same account this still means that for them old API is practicaly deprecated.

I hope this was useful to you in some way. Let me know if you have more questions or if you can specify your problem in more detail and I will try to update answer. `

like image 69
Drago Avatar answered Oct 01 '22 18:10

Drago