This article will help you understand why you need versioning and how you can versioning REST apis. We’ll discuss four methods of version control and compare the different ones.

You will learn

  • Why do we need to version control RESTful apis?
  • What version control is available?
  • How to implement Restful version control?

Why do we need to version RESTful apis

The best version control method is no version control. If you don’t need versioning, you don’t need versioning.

Build backward compatible services to avoid version control as much as possible!

However, there are many situations where versioning is required, but let’s look at the following concrete example:

Initially, you have this version of the Student service that returns the following data:

{
  "name": "Bob Charlie"
}
Copy the code

Later, you wanted to split the student’s name, so you created this version of the service.

{
  "name": {
    "firstName": "Bob"."lastName": "Charlie"}}Copy the code

You can support both requests from the same service, but it becomes more complex as the requirements vary with each release.

In this case, version control becomes essential and mandatory.

Let’s create a simple Maven project for SpringBoot and understand four different ways of versioning RESTful services.

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>

	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>
Copy the code

Several beans for versioning

The first version of beans

@Data
@AllArgsConstructor
public class StudentV1 {
    private String name;
}
Copy the code

The second version of the Bean

@Data
public class StudentV2 {
    private Name name;
}
Copy the code

StudentV2 Specifies the Name entity

@Data
@AllArgsConstructor
public class Name {
    private String firstName;
    private String lastName;
}
Copy the code

Restful version control method

We want to create two versions of the service, one that returns StudentV1 and one that returns StudentV2.

Let’s look at four different ways to create the same service version.

Version control by URI

@RestController
public class StudentUriController {

    @GetMapping("v1/student")
    public StudentV1 studentV1(a) {
        return new StudentV1("javadaily");
    }

    @GetMapping("v2/student")
    public StudentV2 studentV2(a) {
        return new StudentV2(new Name("javadaily"."JAVA Daily Guide")); }}Copy the code

Request: http://localhost:8080/v1/student

Response: {” name “:” javadaily}”

Request: http://localhost:8080/v2/student

Response: {” name “: {” firstName” : “javadaily”, “lastName” : “know JAVA, recorded”}}

Versioning through request parameters

The second approach to versioning is to use request parameters to distinguish versions. An example request is as follows:

  • http://localhost:8080/student/param?version=1
  • http://localhost:8080/student/param?version=2

The implementation is as follows:

@RestController
public class StudentParmController {

    @GetMapping(value="/student/param",params = "version=1")
    public StudentV1 studentV1(a) {
        return new StudentV1("javadaily");
    }

    @GetMapping(value="/student/param",params = "version=2")
    public StudentV2 studentV2(a) {
        return new StudentV2(new Name("javadaily"."JAVA Daily Guide")); }}Copy the code

Request: http://localhost:8080/student/param? version=1

Response: {” name “:” javadaily}”

Request: http://localhost:8080/student/param? version=2

Response: {” name “: {” firstName” : “javadaily”, “lastName” : “know JAVA, recorded”}}

Use custom headers for version control

A third approach to versioning is to use request headers to distinguish versions, as shown in the following example:

  • http://localhost:8080/student/header

    • headers=[X-API-VERSION=1]
  • http://localhost:8080/student/header

    • headers=[X-API-VERSION=2]

The implementation is as follows:

@RestController
public class StudentHeaderController {

    @GetMapping(value="/student/header",headers = "X-API-VERSION=1")
    public StudentV1 studentV1(a) {
        return new StudentV1("javadaily");
    }

    @GetMapping(value="/student/header",headers = "X-API-VERSION=2")
    public StudentV2 studentV2(a) {
        return new StudentV2(new Name("javadaily"."JAVA Daily Guide")); }}Copy the code

The following figure shows how we use Postman to execute a Get request method with a request header.

Request: http://localhost:8080/student/header header: X – API – VERSION = 1

Request: http://localhost:8080/student/header header: X – API – VERSION = 2

Version control by media type

The final method of versioning is to use the Accept Header in a request, as shown in the following example:

  • http://localhost:8080/student/produce

    • headers=[Accept=application/api-v1+json]
  • http://localhost:8080/student/produce

    • headers=[Accept=application/api-v2+json]

The implementation is as follows:

@RestController
public class StudentProduceController {

    @GetMapping(value="/student/produce",produces = "application/api-v1+json")
    public StudentV1 studentV1(a) {
        return new StudentV1("javadaily");
    }

    @GetMapping(value="/student/produce",produces = "application/api-v2+json")
    public StudentV2 studentV2(a) {
        return new StudentV2(new Name("javadaily"."JAVA Daily Guide")); }}Copy the code

The following figure shows how we use Postman to execute a Get method with a request Accept.

Request: http://localhost:8080/student/produce header: Accept = application/API – v1 + json

Request: http://localhost:8080/student/produce header: Accept = application/API v2 + json

Factors influencing version selection

The following factors influence the choice of version control

  • URI contamination – URL versioning and request parameter versioning pollute the URI space.
  • Abuse request headers – Accept request headers are not designed for version control.
  • Caching – If you are using header based versioning, we can’t just be based on URL caching, you need to consider specific request headers.
  • Can it be executed directly in the browser? – If you have non-technical consumers, URL-based versions are easier to use because they can be executed directly on the browser.
  • API Documentation – How can document generation understand that two different urls are versions of the same service?

In fact, there is no perfect version control solution, and you need to make the choice based on the project situation.

The following list shows the different versioning methods used by the major API providers:

  • Versioning of media types

    • Github
  • The custom Header

    • Microsoft
  • The URI path

    • Twitter, Baidu, Zhihu
  • Request parameter control

    • Amazon