I have a Rails backend that serves multiple clients:
Angular JS App
iOS App
At first, I only had the iOS App, and used classical API versioning in rails when substantial changes were brought to the client (naming my versions v1, v2 and so on).
When we came up with the Angular front end, we needed a specific API, so I did a new version that I would use only with Angular (let's say v5).
At that point, v1 through v4 are dedicated to iOS, and v5 to Angular.
Obviously, I can simultaneously update my backend along with my Angular API, since both are served to the client every time they access the website. Therefore, there is no need for the Angular API to be versioned.
However, I'm at that point where I need to update my iOS API, and it is starting to get very wrong : v1..v4 are for iOS, and v5 is taken by Android. So the supposed next iOS API should be... v6? Definitely wrong.
I wanted to know if it was possible to name an API version angular, and thanks to this answer on SO I understand why this is not possible. I'll quote the interesting part for my case:
Ryan Bigg wrote:
I couldn't figure out how to get /api/asdf/users to match, because how do you determine if that is supposed to be a request to /api/<resource>/<identifier> or /api/<version>/<resource>?
Now you understand better my situation, here's the question.
The question
How am I supposed to manage multiple APIs, but which are not really like versions?
Is it possible to subdivide API versions? Like:
api/angular/v1
api/ios/v5 (moving v1..v4 to api/ios/ as well)
api/android/v1
Is there any best practice to do so? Or should I just be using the current API versioning system, knowing which version corresponds to which client?
I think in the end this is a design issue. Your API should be thought of as the methods to access your model in networked MVC. Just as in any MVC the model should be independent of it's view and controller. I think having a different API per client is almost like having a different model for each client, which I don't think is what you are intending.
As an example, (I am assuming your API is Restful), a GET request to
api/v1/user/1
might return a json "view" of user 1, each of your clients should be written to work with that same output. If you decide you will no longer support this, or add or remove some content from the returned json that would break an existing client, then you might bump the version and implement the change on that version
I would suggest your next API version expose all of the resources needed by any clients you currently have, and then overtime update your clients to work with this new unified API. If you find your self making changes to your model (API) that would break an existing client, then you can release a new version, allowing existing clients to continue to work with the old API and new or updated clients can pick up the new version.
A set of automated tests on your API will help identify when you break an existing client.
I am not expert at this, but I did (as a learning project) create a rails app with an api, and I was able to use the same api for android and ios.
In regards to your routing issue quoted from Ryan Bigg, you can resolve it by applying a constraint to the route. For example:
get /api/:type/:version/users/all, to: "users#index", constraints: {type: /(ios|angular)/, version: /\d+/}
Ensuring the the version is a number and the type is either "ios" or "angular", you can easily set up the routes for two separate APIs.
To answer the questions as to whether or not it is possible--yes. Anything is possible, especially with Ruby!
I, first of all, would not have two separate APIs to manage. However, if I did, I would create separate namespaces for each API and name the as AngularAPI and IosAPI. I would just route to them separately. The correct answer will depend on how exactly you've set up your API system.
How would I maintain two separate APIs? (from the comment)
It depends on how substantially different the APIs are. If there are only a few differences, it would make sense to simply use a different controller with different routes. For example, AngularUsersController and IosUsersController. They would both extend a ApiUsersController and alter only what was needed for each platform. This would still allow for proper versioning as it grew, and also keep code duplication at bay.
Related
Can somebody please explain me what exactly is API versioning and why is it needed. I know how to create versions for api on a rails web app, but I really want to know why is it needed. Before somebody downvotes or flags or anything, I googled , I couldn't find any satisfying answer. I would really appreciate it if somebody answers this.
API versioning allows you to have multiple versions of your API and use them at the same time. With this solution, you are assuring backward compatibility for all of the applications integrated with your API.
Simple example
Your API is used by 10 different applications. You are using Basic access authentication, but you noticed that it could be done better. So, you decided to use modify this and use Oauth.
No API versioning
You will have to wait for all of 10 applications to implement changes before releasing the new API version. Otherwise, you will lose the integration. Of course, you can use if/else statements in your code to distinguish which authentication method should you use but this will be not elegant.
API versioning
You can release new API version whenever you want. Then, you can inform your client, that the old API will be deprecated in 3 months, so they have time to implement changes on their side.
Also, you can ask them to add a param to all requests (to choose which API version they will use), and you can set it by the default to the new version. That will allow you to avoid problems with new applications that want to use your API.
Summary(in my opinion):
Pros
1. clean and elegant code (without additional if/else statements)
2. backward compatibility
Cons
1. sometimes you have to duplicate your code
2. it might look like a complex solution at the beginning but don't be scared
Here you can read about two options of API versioning - URL param and HTTP header
I hope that my explanation is clear and helps you understand API versioning
The main reason for versioning your APIs is to provide a constant structure for everybody using them. Let's say you define an initial API for your service (v1) that you send out to your clients. After some time your app changes, and you maybe want to exclude some fields/add new ones. This would be a problem for the client, since their implementation of your API might break if some fields that they are expecting is missing. So you create a v2 with those features, without breaking the initial functionality.
I've come across two scenarios with regards to creating a REST API in Rails and I wonder which one is preferred. Usually
if you know that you're required to have a REST API for your application at start. Does it make sense to have it in a namespace and thereby duplicating the controller logic?
I've seen examples where people have an application already and later figure they need to extend and offer a REST API. The approach to this has been to create new routes with namespacein routes.rb and controllers/api/whatever.... This still yields duplicate code though, but might be more sensible approach. The difference being a stateless machine for the REST API calls.
Can anyone elaborate on the preferred approach, thanks.
If you create a Rails application, and following the usual conventions, you basically end up with a REST API. Unless you are talking about a more specific meaning of the term (which I am not aware of), "REST API" is more a bunch of general characteristics of the API (i.e., things like statelessness, resource-based URIs if using HTTP, etc.).
So to turn the question right back to you: which case are you thinking about where a (conventional) Rails application is not by extension trivially a REST API?
friends,
need your opnion here please.
I a have already a big rails application, but I need to provide a REST API for other clients like mobile.
My doubt is, it is a rigth choice to use the same codebase, that I already have, to develop my API or I need to create it separeted to the existing application?
The API will work with data that the existing application already have or manipulate.
what cons and pros?
Put your API in the same app, within a namespace. If you have to ask the question, putting it in the same app is almost certainly the right answer.
Separate apps introduces an extra layer of complexity and you have to deal with stuff like eg. which app is responsible for database migrations? And if your non-API is handling migrations, then how do you ensure your API is up to date with the latest migrations? You'll likely also end up with some code shared between your app and API, which is more difficult if they're in separate apps. So, put them in the one app.
If you haven't built an API in rails before, this is a great starting point: https://www.codeschool.com/courses/surviving-apis-with-rails (well worth the money)
I have a web application that also provides an API. The API is fairly simple, so I am just handling it in the respond_to block and returning json if requested. Now I want to version my API. I was looking at versionist gem. This mentions using the api_version method in your config/routes.rb to change routes based on API version. I don't understand this though, since I would think the routes would be the same, but the behavior of the response would change.
My question is, do I need separate controllers for my web and API portions? Also, do I need a separate namespace for the API? Or is there a way to keep things as they are now?
There are some things you'd want to do differently when providing an API. One of them is the ability to set an API version so that you can enhance your API by adding a new version without breaking existing clients. If your API is extremely simple you can achieve this by providing a second set of routes that will include the version. You may use versionist for that. However, when you'll need to add versions, the simplest solution (and the one that keeps concerns well separated) will be to hold a separate set of controllers, and keep them thin so there is no code duplication. This may allow you to use additional gems for the API (e.g. RABL, JBuilder or rocketpants). There are railscasts on each of them, I recommend watching them to get some background on API building.
I have a Rails app that has 2 "clients" -- an iOS app reads/writes JSON, and Web browsers that read HTML.
Now, if I said "I want different output for different browsers/clients", we could use different ERB files and render based on User-Agent or similar.
In this way Rails was imagined in the Web world -- where I type "cap deploy", and all of my "instances" are upgraded to the latest version (save active session AJAX calls).
As an iOS dev, however, I'm very used to if blocks in code to deal with different data versions & client app versions. It's painful (but required).
I would love to be able to say "I will magically think of the perfect data structure in version 1.0", but we probably all know that's not true -- I'll want to add & deprecate attributes or even models as time goes.
I don't want to mix all of that versioning logic with my normal HTML (which can upgrade gracefully, per above), so I've thought about:
Having a separate controller or just actions for my API calls from iOS
Writing a "forwarder" that treats the HTML/Web version as a layer on top of the API version
Am I trying to solve a Solved Problem? Are there any resources or guiding philosophies I should know about in undertaking this project?
I suggest you create 2 applications, one for the webapp and one for the API.
You could have an external library with all the models, tests and business logic used in those 2 applications.
You can then lock the api to a certain version of the library if needed.
You can create multiple versions of the API without affecting older versions.
You can implement caching at library level if needed and it will automatically affect all applications.
With this model you can also create specific needs, for example, you may want shorter urls for the api than the real webapp, since you don't care about SEO in the API.
What do you think?
Edit :
Here is what I have in mind, library is in the middle.