表现层状态转换(REST)
表现层状态转换(英语:Representational State Transfer,缩写:REST)是Roy Thomas Fielding博士于2000年在他的博士论文中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。表现层状态转换是根基于超文本传输协议(HTTP)之上而确定的一组约束和属性,是一种设计提供万维网络服务的软件构建风格。符合或兼容于这种架构风格(简称为 REST 或 RESTful)的网络服务,允许客户端发出以统一资源标识符访问和操作网络资源的请求,而与预先定义好的无状态操作集一致化。因此表现层状态转换提供了在互联网络的计算系统之间,彼此资源可交互使用的协作性质(interoperability)。相对于其它种类的网络服务,例如SOAP服务,则是以本身所定义的操作集,来访问网络上的资源。
一、URL设计
1.URL中不能有动词
在Restful架构中,每个网址代表的是一种资源,所以网址中不能有动词,只能有名词,动词由HTTP的 get、post、put、delete 四种方法来表示。
2.URL结尾不应该包含斜杠“/”
这是作为URL路径中处理中最重要的规则之一,正斜杠(/)不会增加语义值,且可能导致混淆。REST API不允许一个尾部的斜杠,不应该将它们包含在提供给客户端的链接的结尾处。
许多Web组件和框架将平等对待以下两个URI:
http://api.canvas.com/shapes/
http://api.canvas.com/shapes
但是,实际上URI中的每个字符都会计入资源的唯一身份的识别中。
两个不同的URI映射到两个不同的资源。如果URI不同,那么资源也是如此,反之亦然。因此,REST API必须生成和传递精确的URI,不能容忍任何的客户端尝试不精确的资源定位。
有些API碰到这种情况,可能设计为让客户端重定向到相应没有尾斜杠的URI(也有可能会返回301 - 用来资源重定向)。
3.正斜杠分隔符”/“必须用来指示层级关系
# GET /authors/12/categories/2
这种 URL 不利于扩展,语义也不明确,往往要想一会,才能明白含义。
更好的做法是,除了第一级,其他级别都用查询字符串表达。
# GET /authors/12?categories=2
4.URL路径中首选小写字母
RFC 3986将URI定义为区分大小写,但scheme 和 host components除外。
5.URL路径名词均为复数
为了保证url格式的一致性,建议使用复数形式。
6.RESTful API对资源的操作
对于rest api资源的操作,由HTTP动词表示
7.CURD操作
- GET: 获取资源
- POST: 新建资源
- PUT:在服务器更新资源(向客户端提供改变后的所有资源)
- PATCH: 在服务器更新资源(向客户端提供改变的属性)
- DELETE:删除资源
8.资源过滤
在获取资源的时候,有可能需要获取某些“过滤”后的资源,例如指定前10行数据
http://api.user.com/schools/grades/classes/boys?page=1&page-size=10
9.动词的覆盖
有些客户端只能使用GET和POST这两种方法。服务器必须接受POST模拟其他三个方法(PUT、PATCH、DELETE)。这时,客户端发出的 HTTP 请求,要加上X-HTTP-Method-Override
属性,告诉服务器应该使用哪一个动词,覆盖POST方法。
POST /api/Person/4 HTTP/1.1
X-HTTP-Method-Override: PUT
X-HTTP-Method-Override指定本次请求的方法是PUT,而不是POST。
10.示例
http://xxx.com/api/users; // GET请求方式 获取所有用户信息
http://xxx.com/api/users/1; // GET请求方式 获取标识为1的用户信息
http://xxx.com/api/users/1; // DELETE请求方式 删除标识为1的用户信息
http://xxx.com/api/users/1; // PATCH请求方式,更新标识为1的用户部分信息
http://xxx.com/api/users; // POST请求方式 添加新的用户
二、返回状态码推荐标准HTTP状态码
有很多服务器将返回状态码一直设为200,然后在返回body里面自定义一些状态码来表示服务器返回结果的状态码。由于rest api是直接使用的HTTP协议,所以它的状态码也要尽量使用HTTP协议的状态码。
客户端的每一次请求,服务器都必须给出回应。回应包括 HTTP 状态码和数据两部分。
# 1xx:相关信息
# 2xx:操作成功
# 3xx:重定向
# 4xx:客户端错误
# 5xx:服务器错误
这五大类总共包含100多种状态码,覆盖了绝大部分可能遇到的情况。每一种状态码都有标准的(或者约定的)解释,客户端只需查看状态码,就可以判断出发生了什么情况,所以服务器应该返回尽可能精确的状态码。
API 不需要1xx状态码,下面介绍其他四类状态码的精确含义
2XX状态码
200状态码表示操作成功,但是不同的方法可以返回更精确的状态码。
POST返回201状态码,表示生成了新的资源;DELETE返回204状态码,表示资源已经不存在。
# GET: 200 OK
# POST: 201 Created
# PUT: 200 OK
# PATCH: 200 OK
# DELETE: 204 No Content
202 Accepted状态码表示服务器已经收到请求,但还未进行处理,会在未来再处理,通常用于异步操作
HTTP/1.1 202 Accepted
{
"task": {
"href": "/api/company/job-management/jobs/2130040",
"id": "2130040"
}
}
3xx 状态码
API 用不到301状态码(永久重定向)和302状态码(暂时重定向,307也是这个含义),因为它们可以由应用级别返回,浏览器会直接跳转,API 级别可以不考虑这两种情况。
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
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:客户端的请求次数超过限额。
5xx 状态码
5xx状态码表示服务端错误。一般来说,API 不会向用户透露服务器的详细信息,所以只要两个状态码就够了。
- 500 Internal Server Error:客户端请求有效,服务器处理时发生了意外。
- 503 Service Unavailable:服务器无法处理请求,一般用于网站维护状态。
三、服务器回应
1.不要返回纯本文
API 返回的数据格式,不应该是纯文本,而应该是一个 JSON 对象,因为这样才能返回标准的结构化数据。所以,服务器回应的 HTTP 头的Content-Type属性要设为application/json。
客户端请求时,也要明确告诉服务器,可以接受 JSON 格式,即请求的 HTTP 头的ACCEPT属性也要设成application/json。下面是一个例子。
GET /orders/2 HTTP/1.1
Accept: application/json
2.发生错误时,不要返回 200 状态码
有一种不恰当的做法是,即使发生错误,也返回200状态码,把错误信息放在数据体里面,就像下面这样。
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "failure",
"data": {
"error": "Expected at least two items in list."
}
}
上面代码中,解析数据体以后,才能得知操作失败。
这张做法实际上取消了状态码,这是完全不可取的。正确的做法是,状态码反映发生的错误,具体的错误信息放在数据体里面返回。下面是一个例子。
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Invalid payoad.",
"detail": {
"surname": "This field is required."
}
}
3.统一返回数据格式
RESTful规范中的请求应该返回统一的数据格式。对于返回的数据,一般会包含如下字段:
1) code: http响应的状态码。
2) status: 包含文本, 比如:'success'(成功), 'fail'(失败), 'error'(异常) HTTP状态响应码在500-599之间为 'fail'; 在400-499之间为 'error', 其他一般都为 'success'。 对于响应状态码为 1xx, 2xx, 3xx 这样的可以根据实际情况可要可不要。
当status的值为 'fail' 或 'error'时,需要添加 message 字段,用于显示错误信息。
3) data: 当请求成功的时候, 返回的数据信息。 但是当状态值为 'fail' 或 'error' 时,data仅仅包含错误原因或异常信息等。
返回成功的响应JSON格式一般为如下:
{
"code": 200,
"status": "success",
"data": [{
"userName": "tugenhua",
"age": 31
}]
}
返回失败的响应json格式为如下:
{
"code": 401,
"status": "error",
"message": '用户没有权限',
"data": null
}