1

I want to enable versioning in my REST service via urls. Need some suggestions/feedback on which is better mechanism?

<myapp_context>/v1/<sub_context>

or

v1/<myapp_context>/<sub_context>

where v1 is the version. I am asking this because a lot of articles mention it like v1/<myapp_context>/<sub_context> but according to me if more than one service is deployed on machine than it would not look good as,

v1/app1/get
v1/app2/get
v1/app3/get

Is there any advantage of providing version in the beginning?

2

It all comes down to routing.

You have two main goals

  1. You want each version of the api not to care that other versions exist.

  2. You want to be able to simply pull the version number out of the http traffic inorder to route that traffic to the correct api instance.

If you put the version in the middle of the query string:

www.myservice.com/users/v1/searchByName?name=test

It implies that the service identified by the host has more than one version. Users might be v1 and Customers might be v2. That breaks rule 1. you want to deploy a v1 service or a v2 service, not half and half.

It is hard to pull the version out of the string.

www.myservice.com/users/v1/searchByName?name=test
www.myservice.com/customer/v1/5
www.myservice.com/orders/france/v1/delivered

imagine writing a regex pattern for your router to get the version out of any of those possible requests.

in comparison, putting it at the start of the query

  • implies a single version for the service on the host.
  • is easy to pull out of the string as it is always the first part
  • can easily be ignored by the service itself. Especially if you are deploying to virtual directories or the like
  • the client can specify it as part of the base url www.myservice.com/v1 and simply append the method path.

It should be mentioned in passing that putting the version in the header will make your urls prettier. But I know that some routing (AWS) cant inspect the header.

2

I want to enable versioning in my REST service via urls.

Best choice: plan for compatibility in your design, such that changes to your implementation do not break existing clients. Cool URI don't change.

Next best choice: a new api is deployed to a new host. Fielding, in 2014

It is always possible for some unexpected reason to come along that requires a completely different API, especially when the semantics of the interface change or security issues require the abandonment of previously deployed software. My point was that there is no need to anticipate such world-breaking changes with a version ID. We have the hostname for that. What you are creating is not a new version of the API, but a new system with a new brand.

<myapp_context>/v1/<sub_context>
v1/<myapp_context>/<sub_context>

There's really not a lot of difference here -- it's worth considering whether one or the other of these is going to be more useful when clients are performing relative resolution of URI.

  • You could as well implement the versioning in the ReverseProxy or in the API Gateway. However, I'm not a big fan of versioning the URI because changing URIs causes breaking change in the client-side. Overall, when previous versions are no longer supported. Managing an ecosystem of APIs, each with different versions is costly. When we are versioning, we are not versioning IDs we are versioning models and logic. We can refer to these different models and logic without having to modify the IDs. – Laiv Jan 29 '18 at 18:58
2

One thing that I think is crucial to a successful versioning strategy is to very clearly separate the versioning of the data structures in your payloads and the versioning of the operations that you need. If you muddle these two things together, you will tend to end up with a incoherent approach.

For example, let's say that you created an API with end point:

.../<employee>/management

and the data output contains this:

"manager": "Boss Hog"

Now all of the sudden you are told that the organization is moving to matrix management* and you need to support this in your API. So you change the data format:

"managers": [
  {"manager": "Boss Hog", "type": "boss"}, 
  {"manager": "Rosco Pico Train", "type": "sheriff"}
]

Don't get hung up on the structure or how you might modify it in a non-breaking way. just assume for the sake of this example that you must change the structure in a way that some clients can't handle without modification.

Note that the URI for this is still the same. This is really crucial because REST (HTTP) provides a nice feature that allows you to support this using custom mime types. That means that your payloads can evolve over time while the URIs are stable.

Now if you need to change the URI structures, that's where your URI versioning comes in. For your own sanity, I suggest that you version the entire thing together even if only a small change is made. Given that, you probably won't want to have to worry about trying to support multiple URI mapping strategies in the same code. By putting the version number up earlier in the path, it make it easier to deploy these separately and use a reverse-proxy to resolve things.

* I do not advocate matrix management.

0

Usually, an API is a single coherent system. While it contains multiple resources, these are all related. The API is deployed as a single software.

But it doesn't have to be that way. The API can also be aggregated from multiple sub-APIs that are largely unrelated to each other and are deployed independently. The API server then performs some routing to translate requests to the correct sub-API.

If your API is a single system, then providing a single version at the root is simplest. This is especially the case when you don't yet need that flexibility. In particular, this allows you to later introduce URLs like /v2/some-sub-api/v7/foo that combine versioning at the root and separate versioning for sub-APIs. You likely don't know in advance where you will need to introduce versioning of sub-APIs.

If the API consists of truly separate sub-APIs (and is also clearly architected and documented like this), then separate versions can make sense. But this introduces a lot of complexity into your URL design. Unless your API is truly gigantic, it might be better to avoid this and expose a unified API.

Note that it's not necessary to “mount” an API at the root of a domain. I.e. it is perfectly legitimate to use example.com/some-app/api/<API> instead of some-app-api.example.com/<API>. However, be aware that sharing a domain also implies that e.g. cookies and other security-relevant properties are shared. This may or may not be desirable. This is more relevant if your APIs are supposed to be used via Ajax requests, less relevant for APIs that will only be used by custom software.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.