RESTFUL API规范

表现层状态转换(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
}

 

 

 

 

 

 

 

 

 

上一篇:SpringBoot系列 - 实现RESTful接口


下一篇:TypesScript + Nodejs + Express + Mongoose 实现 RESTful API 实战视频教程(33 个视频)