RESTful 是目前最流行的 API 设计规范,用于 Web 数据接口的设计。RESTful 的核心思想就是,客户端发出的数据操作指令都是"动词 + 宾语"的结构。比如,GET /articles
这个命令,GET
是动词,/articles
是宾语。动词在HTTP协议的请求方法体现,宾语则在URL中体现。
一、请求方法
通常就是五种 HTTP 方法对应 CRUD 操作:
-
GET:读取(Read)
-
POST:新建(Create)
-
PUT:更新(Update)
-
PATCH:更新(Update),通常是部分更新
-
DELETE:删除(Delete)
有些客户端只能使用GET
和POST
这两种方法。服务器必须接受POST
模拟其他三个方法(PUT
、PATCH
、DELETE
)。这时,客户端发出的 HTTP 请求,要加上X-HTTP-Method-Override
属性,告诉服务器应该使用哪一个动词,覆盖POST
方法。
POST /api/Person/4 HTTP/1.1
X-HTTP-Method-Override: PUT
二、URL
2.1 使用名词
宾语就是 API 的 URL,是 HTTP 动词作用的对象。它应该是名词,不能是动词。
2.2 使用名词复数
-
API表示获取一个数据集合时,使用复数表示,如
GET /articles
(获取所有文章) -
API表示获取一个数据集合中的单个数据元素时,这个集合也建议使用复数,如
GET /articles/2
(获取编号为2的文章)
2.3 避免多级 URL
资源需要多级分类时,写出多级的 URL不利于扩展,语义也不明确:
GET /authors/12/categories/2
更好的做法是,除了第一级,其他级别都用查询字符串表达:
GET /authors/12?categories=2
GET /articles?published=true
三、响应状态码
客户端的每一次请求,服务器都必须给出回应。以下四种状态码,覆盖了绝大部分 API响应 可能遇到的情况:
-
2xx
:操作成功 -
3xx
:重定向 -
4xx
:客户端错误 -
5xx
:服务器错误
每一种状态码都有标准的(或者约定的)解释,客户端只需查看状态码,就可以判断出发生了什么情况,所以服务端应返回尽可能精确的状态码。
3.1 2xx状态码
-
GET:200 OK
-
POST:201 Created(表示生成了新的资源)
-
PUT:200 OK
-
PATCH:200 OK
-
DELETE:204 No Content(表示资源已经不存在)
-
202 Accepted(表示服务器已经收到请求,但还未进行处理,会在未来再处理,通常用于异步操作)
3.2 3xx状态码
API 级别用到的的3xx状态码主要是303 See Other
,表示参考另一个 URL。
它与302
和307
的含义一样,也是"暂时重定向",区别在于302
和307
用于GET
请求,而303
用于POST
、PUT
和DELETE
请求。收到303
以后,浏览器不会自动跳转,而会让用户自己决定下一步怎么办,例如:
HTTP/1.1 303 See Other
Location: /api/orders/12345
3.3 4xx状态码
4xx
状态码表示客户端错误,主要有下面几种:
-
400 Bad Request
:服务器不理解客户端的请求,未做任何处理。 -
401 Unauthorized
:用户未提供身份验证凭据,或者没有通过身份验证。 -
403 Forbidden
:用户通过了身份验证,但是不具有访问资源所需的权限。 -
404 Not Found
:所请求的资源不存在,或不可用。 -
405 Method Not Allowed
:用户已经通过身份验证,但是所用的 HTTP 方法不在他的权限之内。 -
410 Gone
:所请求的资源已从这个地址转移,不再可用。 -
415 Unsupported Media Type
:客户端要求的返回格式不支持。如:API 只能返回 JSON 格式,但是客户端要求返回 XML 格式。 -
422 Unprocessable Entity
:客户端上传的附件无法处理,导致请求失败。 -
429 Too Many Requests
:客户端的请求次数超过限额。
3.4 5xx状态码
5xx
状态码表示服务端错误。一般来说,API 不会向用户透露服务器的详细信息,所以只要两个状态码就够了。
-
500 Internal Server Error
:客户端请求有效,服务器处理时发生了意外。 -
503 Service Unavailable
:服务器无法处理请求,一般用于网站维护状态。
四、响应体
4.1 返回json
对象
-
请求头中的
ACCEPT
属性要设成application/json
,告诉服务器,可以接受 JSON 格式 -
响应头中的
Content-Type
属性要设为application/json
4.2 返回与状态码匹配的内容
状态码应与响应体的内容匹配,如下示例就不匹配:
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "failure",
...
}
响应内容应该与状态码体现的语义相同或相配合,易于理解,修改后:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Invalid payoad.",
...
}
4.3 提供连接
在设计良好的RESTful API 中,客户端只需知道几个*资源的 URL,其他资源的 URL 则从响应中包含的链接上发掘。这就好比浏览网络时,你在自己知道的网页中点击链接发掘新网页一样。
例如GitHub 的 API 都在 api.github.com 这个域名。访问它,就可以得到其他 URL:
{
...
"feeds_url": "https://api.github.com/feeds",
"followers_url": "https://api.github.com/user/followers",
"following_url": "https://api.github.com/user/following{/target}",
"gists_url": "https://api.github.com/gists{/gist_id}",
"hub_url": "https://api.github.com/hub",
...
}
参考
-
RESTful API 最佳实践,by 阮一峰
-
GitHub REST API,by Github doc
-
Web API design,by Microsoft Azure