初尝RESTFul规范
RESTFul是一种HTTP API接口规范,只要满足的RESTFul规范,即可称为RESTFul API。
既然是接口,我们先来了解一下,他和传统的API接口有何不同吧。
本文以尽量简单明了的文字来介绍、描述,只讲核心内容,仅供入门指引。
1 与传统API的区别
RESTFul世界中,一切皆抽象为资源(Resource)。
用户是资源,文章是资源、评论是资源,抽象一点的session、token等均是资源。
下面例子,我们通过以下几个常用的HTTP方法对资源(图书)进行操作。
RESTFul中:
操作 | 方法 | 示例 |
---|---|---|
查询 | GET | GET /books |
增加 | POST | POST /books |
修改 | PUT | PUT /books |
删除 | DELETE | DELETE /books |
传统API中:
操作 | 方法 | 示例 |
---|---|---|
查询 | GET | GET /api/book/getBook |
增加 | POST | POST /api/book/addBook |
修改 | POST | POST /api/book/updateBook |
删除 | GET/POST | POST /api/book/deleteBook |
2 URL设计
RESTFul API规范很简单,关键只需满足这一点。
动词(HTTP动作) + 名词(资源)
2.1 常用动作
通常我们采用以下5种 HTTP方法(动作)。
- GET:查询(Read)
- POST:增加(Create)
- PUT:更新(Update)
- PATCH:部分更新,不常用(Update)
- DELETE:删除(Delete)
2.2 名词尽量复数
名词尽量采用复数(语义更明确,但并不强制),举个例子:
类型 | 操作 | 示例 |
---|---|---|
单数 | 获取所有图书 | GET /book |
单数 | 获取ID为1的图书 | GET /book/1 |
复数 | 获取所有图书 | GET /books |
复数 | 获取ID为1的图书 | GET /books/1 |
不难发现,复数形式语义更明确。
2.3 方法 & 过滤参数
方法应当以路径(path)的方式传递:
示例:
- 获取部门:GET /departments
- 获取部门下的所有员工:GET /departments/{id}/employees
- 获取部门下的某个员工:GET /departments/{id}/employees/{id}
- 文章点赞:PUT /articles/{id}/praise
过滤参数应当以查询字符串(QueryString)的方式传递:
示例:
- 获取第1页,每页显示10条:GET /books?page=1&per_page=10
- 获取已经发布的文章:GET /articles?published=true(或等于1也行)
何时使用方法,何时使用过滤参数?
区别:
- 方法:获取后的数据结构不同了。
- 过滤参数:获取后的数据结构还是一样的,只是数量减少了。
3 响应请求
必须
尽可能返回意义准确的HTTP状态码,不要一味的返回200
状态码。
状态码主要分为5类:
在RESTFul中通常我们只需要用到2XX、4XX、5XX。
- 1XX:信息类
- 2XX:成功类
- 3XX:重定向
- 4XX:客户端错误
- 5XX:服务器错误
有关状态码的详细参考:HTTP状态码
常用HTTP状态码:
响应码 | 说明 |
---|---|
200 OK | 请求已成功 |
201 Created | 资源已创建 |
204 No Content | 请求已成功,但无返回内容 |
304 Not Modified | 缓存有效 |
400 Bad Request | 语义有误,当前请求无法被服务器理解,请求参数错误 |
401 Unauthorized | 当前请求需要用户认证(登录) |
403 Forbidden | 用户已认证(登录),但权限不足 |
404 Not Found | 请求源未在服务器上被发现 |
405 Method Not Allowed | 请求方法不能被用于请求相应的资源,如使用PUT方法访问只接受POST方法的API |
500 Internal Server Error | 服务端内部错误 |
502 Bad Gateway | 网关错误 |
504 Gateway Timeout | 网关超时 |
3.1 成功类
对于成功类,除了
GET
请求需要返回响应体(数据)之外,其他请求均可不返回响应体。
获取文章:
返回
200
状态码,返回的数据不需要进行多余的包装。
GET /articles/1
HTTP/1.1 200 OK
{
"title": "文章标题",
"content": "文章内容"
}
增加文章:
返回
201
状态码,可选返回响应体(创建后的对象)。
POST /articles
HTTP/1.1 201 Created
{
"id": 1,
"title": "文章标题",
"content": "文章内容"
}
HTTP/1.1 201 Created
更新文章:
若返回响应体(更新后的对象)则使用
200
状态码,否则使用204
状态码。
PUT /articles/1
HTTP/1.1 200 OK
{
"id": 1,
"title": "文章标题",
"content": "文章内容"
}
HTTP/1.1 204 No Content
删除文章:
返回
204
状态码。
DELETE /articles/1
HTTP/1.1 204 No Content
3.2 错误类
建议为所有错误的请求响应体加上错误代码
、消息
字段。
错误代码
建议由HTTP状态码
+ 自定义的错误代码
组成。
例如:客户端错误状态码为400
,账号或密码错误代码为01
(自定义),组成40001
错误代码。
3.2.1 客户端错误
登录失败:
POST /tokens/login
HTTP/1.1 400 Bad Request
{
"error_code": 40001,
"message": "用户名或密码错误"
}
用户名已被注册:
POST /users
HTTP/1.1 400 Bad Request
{
"error_code": 40002,
"message": "用户名已被注册"
}
未登录:
HTTP/1.1 401 Unauthorized
{
"error_code": 40101,
"message": "用户未登录"
}
权限不足:
HTTP/1.1 403 Forbidden
{
"error_code": 40301,
"message": "权限不足"
}
文章不存在或已被删除:
HTTP/1.1 404 Not Found
{
"error_code": 40401,
"message": "文章不存在或已被删除"
}
3.2.2 服务器错误
HTTP/1.1 500 Internal Server Error
{
"error_code": 50001,
"message": "服务器内部错误,请稍后再试或联系管理员"
}