理解 REST 设计

2020.07.16 14:37

REST 的起源

REST 首次提出是 2000 年 Roy Thomas Fielding 发表的博士论文。REST 的全称是表现层状态转移Representational State Transfer),实际上可以认为是超文本传输“HTT”Hypertext Transfer)的进一步抽象。

REST 的相关概念

资源(Resource)

资源可以理解为一个应用中的实体,访问一个应用时,我们会与许多资源交互,比如阅读一篇文章时,文章属于一个资源、文章的每一条评论属于一个资源、每一条评论所对应的用户也是一个资源。每一种资源都可以用特定的 URI 指定,比如 /article/233 可以指定 id 为 233 的文章。

表现层(Representation)

也叫做“表征”,对应的是不同资源的不同表现形式,比如用浏览器访问一篇文章,浏览器向服务器发送“我需要这个文章的 HTML 资源”,服务器则返回 HTML 格式的文章,而使用 APP 或者 SPA 应用向服务器交互则可能返回的是 json 格式的文章。服务器返回什么格式的资源往往取决于 HTTP Header 中的 Content-Type 字段,比如Content-Type : application/json; charset=utf-8,则说明该资源会以 JSON 的格式来返回,请使用 UTF-8 字符集进行处理。

状态转移(State Transfer)

访问一个应用,就是客户端与服务端进行交互的一个过程。而当前访问的上下文信息也就表示着当前的状态。我们平时说 HTTP 是无状态协议是指状态存在服务端,如果想要改变状态,那么客户端就需要进行某些操作,让服务端发生“状态转移”。

资源都对应着一个名词命名 URI,恰好 HTTP 定义好了几种方法(GET、POST、PUT、PATCH、DELETE...)就可以表示对资源状态的变更。

REST API 设计概述

资源

每个 URI 表示一种资源,不能使用动词,比如获取文章不应该使用/articles/1/show,正确的 URI 应该是 /articles/1,对于获取这个操作,使用 GET 方法。

动作

对于资源的几种动作要使用 HTTP 的几种方法

方法动作
GET获取资源
POST新增资源
PUT整体更新资源
PATCH局部更新资源
DELETE删除资源

示例:

信息过滤

如果不想要获取某 URI 下所有资源,可以利用 HTTP 的 query 参数进行过滤信息。

示例:

参数的设计允许存在冗余,即允许 API 路径和 URL 参数偶尔有重复。比如,GET /articles/233/commentsGET /comments?article_id=233 的含义是相同的。

状态码

利用 HTTP 规范的状态码可以表示操作的不同结果。

示例

异常信息

如果状态码不是成功状态码,就应该返回错误信息,如

HTTP/1.1 400 INVALID REQUEST

{
    "message": "参数格式错误"
}

超文本驱动

超文本驱动期望的是可以让客户端无需查阅文档也能知道后续可以进行的操作,也就是接下来可以进行的状态转移,由超文本自身驱动

比如,当一个博客管理员调用了下面的接口后

GET /articles

服务端传回来的响应信息应该包括文章列表和可能的后续操作,如

{
    "data": [
        {
            "id": 1,
            "title": "第一篇文章",
            "links": [
                {
                    "rel": "查看详情",
                    "link": "/articles/1",
                    "method": "get"
                },
                {
                    "rel": "删除文章",
                    "link": "/articles/1",
                    "method": "delete"
                }
            ]
        }
    ]
}

参考资料

  1. 《凤凰架构》:REST 设计风格

  2. 理解 RESTful 架构

  3. RESTful API 设计指南

  4. HTTP 响应代码