> For the complete documentation index, see [llms.txt](https://anjia1.gitbook.io/web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://anjia1.gitbook.io/web/web/evolution/rest.md).

# RESTful 设计风格

用 URL 定位资源，用 HTTP 方法描述操作

REST（Representational State Transfer，表现层状态转换）是基于 HTTP 之上的一组约束和属性，其目的是便于不同程序在网络中互相传递信息。

符合或兼容这种风格（简称为 REST 或 RESTful）的网络服务，允许客户端发出以 URL （统一资源标识符）访问和操作网络资源的请求，而与预先定义好的无状态操作集一致化。符合 REST 设计风格的 Web API 称为 RESTful API。

REST 鼓励基于 URL 来组织系统功能，充分利用 HTTP 本身的语义，而不是仅仅将 HTTP 作为一种远程数据传输协议。

通常情况：

1. 域名和主域名分开
   * `api.example.com`
   * `example.com/api/`
2. 带有版本控制
   * `api.example.com/v1`
   * `api.example.com/v2`

## 使用 URL 定位资源

每个 URL 都代表着一种资源，资源应当是一个名词，而且大部分情况是名词的复数，尽量不要在 URL 中出现动词。

<table data-header-hidden><thead><tr><th width="633"></th></tr></thead><tbody><tr><td><p>POST <code>https://api.xx.com/createTopic</code>    ❌</p><p>POST <code>https://api.xx.com/topics</code>               <mark style="color:green;">✔</mark></p></td></tr><tr><td>GET <code>https://api.xx.com/topic/show/1</code>    ❌<br>GET <code>https://api.xx.com/topics/1</code>             <mark style="color:green;">✔</mark></td></tr><tr><td><p>POST <code>https://api.xx.com/topics/1/comments/create</code>     ❌</p><p>POST <code>https://api.xx.com/topics/1/comments</code>                    <mark style="color:green;">✔</mark></p></td></tr><tr><td>POST <code>https://api.xx.com/topics/1/comments/100/delete</code>    ❌<br>DELETE <code>https://api.xx.com/topics/1/comments/100</code>               <mark style="color:green;">✔</mark></td></tr></tbody></table>

比如 GitHub 的 Restful HTTP API 设计：

* GET `/issues`                             列出所有的 issue
* GET `/orgs/:org/issues`        列出某个项目的 issue
* GET `/repos/:owner/:repo/issues/:number`                     获取某个项目的某个 issue
* POST `/repos/:owner/:repo/issues`                                    为某个项目创建 issue
* PATCH `/repos/:owner/:repo/issues/:number`                 修改某个项目的某个 issue
* PUT `/repos/:owner/:repo/issues/:number/lock`           锁住某个项目某个 issue
* DELETE `/repos/:owner/:repo/issues/:number/lock`     接收某个项目某个 issue

大部分情况，我们访问的是某个资源集合，想得到单个资源可以通过资源的 `id` 或 `number` 等唯一标识获取。某些情况，资源会是单数形式，例如某个项目某个 issue 的锁，每个 issue 只会有一把锁，所以它是单数。资源的设计可以嵌套，表明资源与资源之间的关系。

* GET `/users`                              获取所有用户
* GET `/teams/:team/users`     获取某团队所有用户
* POST `/users`                  创建用户
* PATCH/PUT `/users`        修改某个用户数据
* DELETE `/users`               删除某个用户数据

## 用 HTTP 方法描述操作

* GET 获取资源，单个或多个
* POST 创建资源
* PUT/PATCH 更新资源，客户端提供完整的资源数据
* DELETE 删除资源
