如何理解RESTful API

文章目录

    • 一、基本概念
        • 1.1 什么是REST
        • 1.2 RESTful主要实现什么
    • 二、域名与版本
        • 2.1 域名的设计
        • 2.2 版本的设计
    • 三、URL的设计
        • 3.1 动词 + 宾语的格式
            • 3.1.1 HTTP动词
            • 3.1.2 宾语的要求
        • 3.2 符合RESTful的动词 + 宾语形式
        • 3.3 过滤信息
    • 四、状态码设计
        • 4.1 概述
        • 4.2 2xx 状态码
        • 4.3 3xx 状态码
        • 4.4 4xx 状态码
        • 4.5 5xx 状态码
    • 五、服务器的响应
        • 5.1 不要返回纯本文
        • 5.2 提供超媒体(Hypermedia API)


一、基本概念

1.1 什么是REST

REST全称是Representational State Transfer,中文意思是表征性状态转移
它首次出现在2000年Roy Fielding的博士论文中,Roy Fielding是HTTP规范的主要编写者之一

他在论文中提到:"我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构

REST指的是一组架构约束条件和原则。“如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。”

REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束
RESTful 是目前最流行的 API 设计规范,用于 Web 数据接口的设计


1.2 RESTful主要实现什么

首先REST指的是表征性状态转移,而这里的表征性实际指的就是网络当中的资源
任何事物,只要有被引用到的必要,它就是一个资源:

  • 用户的手机号
  • 用户的家庭住址
  • 某个业务的所有属性

在Web中我们使用统一资源定位符URI(Uniform Resource Identifier)定义一个资源,以此识别一个资源
URI既可以看成是资源的地址,也可以看成是资源的名称
为了让URI更加清晰、直观、明了,URI的设计应该遵循可寻址性原则,具有自描述性,需要在形式上给人以直觉上的关联
因此定义RESTful API,主要就是规范软件架构风格、设计风格,使其遵循一定的设计原则和约束条件,使得基于RESTful风格设计接口可以更简洁,更有层次,更易于实现缓存等机制。


二、域名与版本

2.1 域名的设计

尽量将API部署在专用域名之下

https://api.example.com

如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下

https://example.org/api/

2.2 版本的设计

将API的版本号放入URL

http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo

版本号也可以在HTTP请求头信息的Accept字段中进行区分

Accept: vnd.example-com.foo+json; version=1.0
Accept: vnd.example-com.foo+json; version=1.1

三、URL的设计

3.1 动词 + 宾语的格式

RESTful 的核心思想就是,客户端发出的数据操作指令都是"动词 + 宾语"的结构。比如,GET /papers这个命令,GET是动词,/papers是宾语
也就是说在设计URL是需要遵循"动词 + 宾语"的结构

3.1.1 HTTP动词

HTTP动词是对资源的具体操作类型, 就是所谓的请求方式
常用的HTTP动词有下面四个(括号里是对应的SQL命令)

GET(SELECT):从服务器取出资源(一项或多项)
POST(CREATE):在服务器新建一个资源
PUT(UPDATE):在服务器更新资源(全部更新)
DELETE(DELETE):从服务器删除资源

# 其他动词
PATCH(UPDATE):在服务器更新资源(部分更新)
HEAD:获取资源的元数据
OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的

动词补充:
有些客户端只能使用GETPOST这两种方法。服务器必须接受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

3.1.2 宾语的要求

宾语就是接口具体的 URL,是 HTTP 动词作用的对象

  • RESTful API规定宾语(URL)只能有名词,不能有动词,而且所用的名词往往与数据库的表名对应
  • URL中的名词应该使用复数,无论子资源或者是其他所有资源
    比如,/papers这个 URL 就是正确的,而下面的 URL 不是名词,所以都是错误的
/getPapers
/listCarts
/retreiveAllBooks
  • 基于上述原则,一个符合RESTful的API设计可一如下示例
# 获取单个产品:
http://127.0.0.1:8888/papers/1

# 获取所有产品: 
http://127.0.0.1:8888/papers

3.2 符合RESTful的动词 + 宾语形式

基于上面提到的动词+宾语设计原则,这里给出几个常见的范例

GET /librarys  # 列出所有图书馆
POST /librarys  # 新建一个图书馆(上传文件)
GET /librarys/ID  # 获取某个指定图书馆的信息
PUT /librarys/ID  # 更新某个指定图书馆的信息(提供该图书馆的全部信息)
PATCH /librarys/ID  # 更新某个指定图书馆的信息(提供该图书馆的部分信息)
DELETE /librarys/ID  # 删除某个图书馆
GET /librarys/ID/books  # 列出某个指定图书馆的所有书籍
DELETE /librarys/ID/books/ID  # 删除某个指定图书馆的指定书籍

3.3 过滤信息

即当记录的数量很多时 , 通常需要利用资源的一些属性对结果进行过滤
如果将资源的属性作为URL的宾语往往不利于扩展,通常使用查询字符串表示过滤信息
常见参数:

?limit=20  # 指定返回记录的数量
?offset=20  # 指定返回记录的开始位置
?page=2&per_page=100  # 指定第几页,以及每页的记录数,多个条件使用“&”拼接
?book_type=historical  # 指定书本分类条件

四、状态码设计

4.1 概述

状态码是HTTP协议内容的一部分,它代表了服务器响应客户端请求的结果,不同的状态码对应服务器不同的响应状态
我们当然可以随心所欲的让服务器返回状态码,但是这往往会给客户端带来困扰
因此符合RESTful的状态码设计应该能够准确反映服务器的响应状态
HTTP 状态码就是一个三位数,分成五个类别:

1xx:相关信息
2xx:操作成功
3xx:重定向
4xx:客户端错误
5xx:服务器错误

这五大类总共包含100多种状态码,覆盖了绝大部分可能遇到的情况
每一种状态码都有标准的(或者约定的)解释,客户端只需查看状态码,就可以判断出发生了什么情况,所以服务器应该返回尽可能精确的状态码
其中1xx通常用于要求客户端继续发送更多请求相关的数据或信息,在RESTful API中基本涉及不到


4.2 2xx 状态码

200状态码表示操作成功,但是不同HTTP请求的方法可以返回更精确的状态码

GET: 200 OK  # 服务器成功返回用户请求的数据
POST/PUT/PATCH: 201 CREATED  # 用户新建或修改数据成功
ALL Type: 202 Accepted  # 表示一个请求已经进入后台排队(异步任务)
DELETE: 204 No Content  # 用户删除数据成功

其中202异步任务返回结果的例子

HTTP/1.1 202 Accepted

{
  "task": {
    "href": "/api/company/job-management/jobs/2130040",
    "id": "2130040"
  }
}

返回结果
当请求成功时,对于不同的HTTP请求,服务器也应该返回不同的结果

GET /librarys  # 请求所有资源,返回资源对象的列表
GET /librarys/ID  # 请求单个资源,返回单个资源对象
POST /librarys  # 返回新生成的资源对象
PUT /librarys/ID  # 更新单个资源,返回完整的单个资源对象
PATCH /librarys/ID  # 部分更新单个资源,返回完整的单个资源对象
DELETE /librarys/ID  # 删除单个对象,返回一个空文档

4.3 3xx 状态码

API 用不到301状态码(永久重定向)和302状态码(暂时重定向,307也是这个含义),因为它们可以由应用级别返回,浏览器会直接跳转,API 级别可以不考虑这两种情况
API 用到的3xx状态码,主要是303 See Other,表示参考另一个 URL
它与302307的含义一样,也是"暂时重定向",区别在于302307用于GET请求,而303用于POSTPUTDELETE请求
收到303以后,浏览器不会自动跳转,而会让用户自己决定下一步怎么办。下面是一个例子:

HTTP/1.1 303 See Other
Location: /api/orders/12345

301: 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302: 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI


4.4 4xx 状态码

4xx状态码表示客户端错误,主要有下面几种

400 INVALID REQUEST  # POST/PUT/PATCH:用户发出的请求有错误,服务器没有进行新建或修改数据的操作
401 Unauthorized  # All Type:表示用户没有权限(令牌、用户名、密码错误)
403 Forbidden  # All Type:表示用户得到授权,但是权限不足导致访问被禁止
404 NOT FOUND  # All Type:用户发出的请求针对的是不存在的记录
406 Not Acceptable  # GET:服务器无法根据客户端请求的内容特性完成请求
410 Gone  # GET:所请求的资源已从这个地址转移,不再可用
415 Unsupported Media Type  # 客户端要求的返回格式不支持。比如,API 只能返回 JSON 格式,但是客户端要求返回 XML 格式
422 Unprocesable entity # POST/PUT/PATCH:客户端上传的附件无法处理,导致请求失败
429 Too Many Requests  # 客户端的请求次数超过限额

4.5 5xx 状态码

5xx 状态码表示服务端错误。一般来说,API 不会向用户透露服务器的详细信息,所以只要两个状态码就够了

500 Internal Server Error  # 客户端请求有效,服务器处理时发生了意外
503 Service Unavailable  # 服务器无法处理请求,一般用于网站维护状态

五、服务器的响应

5.1 不要返回纯本文

API 返回的数据格式,不应该是纯文本,而应该是一个 JSON 对象,因为这样才能返回标准的结构化数据
所以,服务器回应的 HTTP 头的Content-Type属性要设为application/json
客户端请求时,也要明确告诉服务器,可以接受JSON 格式,即请求的 HTTP 头的ACCEPT属性也要设成application/json

响应头示例

GET /orders/2 HTTP/1.1 
Accept: application/json

5.2 提供超媒体(Hypermedia API)

RESTful API最好做到Hypermedia(即返回结果中提供链接,指向其他API)
这样的话,用户只要记住一个 URL,不用查看接口文档,就可以发现其他的 URL
例如https://api.github.com/

{
    "current_user_url": "https://api.github.com/user",
    "current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}",
    "authorizations_url": "https://api.github.com/authorizations",
    "code_search_url": "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}",
    "commit_search_url": "https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}",
    "emails_url": "https://api.github.com/user/emails",
    // ...
}

参考资料:
http://www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html

你可能感兴趣的:(网络通信)