-1

In our application we have adapted URI versioning scheme.

Eg: server.com/v2/resource1

Now there are two school of thought in the team:

  1. We should not expose resource level version to client, instead we should give one version to them. If they call /v2/resource1 and v2 is not present for resource1 then we should reroute the request to /v1/resource1 internally.

  2. We should expose resource level versioning to client. If the call /v2/resource1 and v2 is not present for resource1 then we should send simple 404 error response to client.

The benefit of the first approach is that client doesn’t have to worry about granular level of versioning. But this approach stops us from incremental refactoring of the end points as that will break backward compatibility, as once we expose v2, for client each resource is at v2 version.

The second approach gives us better control over incremental refactoring and clear understanding of the resource version from client perspective as well.

Thoughts?

  • In the words of Fielding [Don't](https://www.infoq.com/articles/roy-fielding-on-versioning&quot%3b&gt%3b/). In a REST architecture a server should teach a client what it needs to know, similar to the Web where a server sends HTML pages containing links and forms a browser can render to the user. There is no need for v2, v3, ..., vN in any way as the communication is based on standardized representation formats both client and server understand. The question should not be which media-type to support but how many different ones to increase likelihood for interoperability – Roman Vottner Nov 08 '19 at 04:46

2 Answers2

2

IMO API versioning should be at the API level (note: by API I mean a set of resources/routes and their operations). Even if you only need to bump the version of a single specific operation for a single route; all existing API operations should also be accessible using the new version e.g. you should not have the scenario where one operation is accessible at /api/v2/template/thing, but a second operation in the same API is only at accessible at /api/v1/template/item and not /api/v2/template/item. This would add a lot of confusion to the API consumers.

We use .NET Core at my current company. To achieve the above, API controller classes are tagged with ApiVersion attributes for all known versions. Specific operations that are not the latest version are tagged with the MapToApiVersion attribute - latest versions of operations do not be tagged with a specific MapToApiVersion e.g.

[ApiVersion("1.0")]
[ApiVersion("2.0")]
[ApiController]
[Route("api/v{version:apiVersion}/template/test")]
public class TestController : ControllerBase
{
   [HttpGet]
   [MapToApiVersion("1.0")]
   public IActionResult Get()
   {
      return Ok(nameof(Get));
   }

   [HttpGet]
   public IActionResult GetV2()
   {
      return Ok(nameof(GetV2));
   }

In the example above; the GetV2 operation is basically the default route for any version that's not explicitly handled e.g. HTTP GET to /api/v2/template/test.

This approach gives you the benefit of; a) client doesn’t have to worry about granular level of versioning, and b) can still do incremental refactoring of the end points that won't break backward compatibility.

Ryan.Bartsch
  • 3,698
  • 1
  • 26
  • 52
  • When I say resource versioning I mean to say every operation on that particular resource will be at one version. /template and template/op1and any type of http operation on this will be at same version. if we have something like /Person and /Person/{id}/Address this should be one version but the version not necessarily same as template resource. All the Operation on template resource will be at one version and the operations on Person resource may be at different version. – RAJESH KUMAR Nov 08 '19 at 04:30
  • In your example I assume Template is one resource and hence any api pertaining to that resource be it /template or /template/op1 will always be on one version. We may have different resources like template all the apis of that resource will be on same version , but the versions of both the resources need not be same. – RAJESH KUMAR Nov 08 '19 at 04:41
  • You can have multiple resources/routes and they'd all follow the same approach - all routes (e.g. /template, /thing, /item) would define the same list of versions so that clients don't have to manage different versions for different resources. The approach I suggested gives you this as well as the ability to do incremental refactoring of the resources/operations that shouldn't break backward compatibility (if done correctly). – Ryan.Bartsch Nov 08 '19 at 06:00
  • FYI., when I mention API in my initial response, I mean a *set* of routes with different RESTful operations e.g. GET, POST, etc. – Ryan.Bartsch Nov 08 '19 at 06:02
0

As per the REST specifications having versioning information in the URL is not recommended since a REST URI should refer to a unique resource. But this recommendation is not heeded by almost all of the most popular REST based APIs out there.

To make things easier, deploy the resource1 in v2 iff there isn't a new version available for it. If there is a new version available then deploy that one in v2.

Keep both the versions running and give the time for clients to upgrade and drop the older version after a while.

Khanna111
  • 3,627
  • 1
  • 23
  • 25
  • The main issue we are facing is backward compatibility as our consumer is App. Now if we allow them to use v2 for a resource which is actually not on v2. And after a while we try to implement the v2 , it breaks the backward compatibility. So once we release the v2 apis we can’t upgrade the remaining v1 apis to v2. As client will always call v2. – RAJESH KUMAR Nov 08 '19 at 04:36