Why?

发布出去的 API 就像泼出去的水,不进行版本控制,对某些调用者来说一定会是灾难性的。

举个例子。比如你在一家公司负责后端 API 的开发,同时给公司的 Android 和 iOS 客户端提供接口。
在 1 月份的时候,你开发了一个接口,用于获取文章的详情

1
2
3
4
5
6
7
8
9
10
@GET /post/:id
//response
{
"title": "xxx",
"content": "xxx",
"author": {
"id": 123,
"name": "xxx"
}
}

开发完成后,你很 happy 地告诉客户端同学,获取文章详情就调我这个接口吧,一点问题都没有。客户端同学也很 happy 地调用了。2 月份,客户端开发完成,顺利发布 1.0 版本。这个时候,还没有遇到任何问题。

3 月份的时候,设计变了,文章支持了多作者!所以现在那个相同的 API 返回的结果可能是这样的,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@GET /post/:id
// response
{
"title": "xxx",
"content": "xxx",
"author": [
{
"id": 123,
"name": "xxx"
},
{
"id": 456
"name": "xxx"
}
]
}

Boom! 这下可糟了,如果 API 产生了这么重大的变化,那么已经发出去的 1.0 版本的客户端可怎么办啊?(开发过客户端的同学都知道,同一个接口返回这么「脏」的数据是会 crash 的)。这个时候,就需要 API versioning(版本化)了。

How?

通常来说,API 版本控制有以下几种方式:

/api/v1/xxx

直接把 API 的版本信息放到 URL 里面,新浪是这么做的。

优点:直观
缺点:URL 被污染了,很不优雅

API-VERSION: 3.0

使用自定义的 header 识别 API 的版本,知乎目前是这么做的。

优点:URL 变得很干净
缺点:不直观,代码不好组织,而且容易产生向后兼容的问题(至少知乎的某些 API 是这样的,一般这种对于 header 的修改都是全局的,某些 API 说好了可以升级到 2.0,但是我调用 2.0 的 /singin 都登录不上)

Accept: application/vnd.xxx.v2+json

修改 header 中的 Accept 字段,Github 是这么做的。

优缺点同上