RESTful API 全面详解
什么是 RESTful API?
RESTful API 是一种基于 REST(Representational State Transfer,表述性状态转移)架构风格设计的 API。它不是标准或协议,而是一种设计风格,用于创建可扩展、可靠且易于维护的 Web 服务。
RESTful API 设计规范
1. 资源命名规范
使用名词而非动词
http
apl
# 正确 - 使用名词
GET /users
GET /users/123
POST /users
# 错误 - 使用动词
GET /getUsers
POST /createUser使用复数形式
http
# 推荐使用复数
GET /users
GET /users/123/orders
# 单数形式(不推荐)
GET /user
GET /user/123/order资源层次结构
http
# 表示层次关系
GET /users/123/orders # 用户123的所有订单
GET /users/123/orders/456 # 用户123的订单456过滤、排序、分页
http
# 使用查询参数
GET /users?role=admin&active=true # 过滤
GET /users?sort=name,-age # 排序(name升序,age降序)
GET /users?page=2&limit=20 # 分页
GET /users?fields=id,name,email # 字段选择2. HTTP 方法使用规范
| HTTP 方法 | 描述 | 幂等性 | 安全性 |
|---|---|---|---|
| GET | 获取资源 | 是 | 是 |
| POST | 创建资源 | 否 | 否 |
| PUT | 更新或创建资源 | 是 | 否 |
| PATCH | 部分更新资源 | 否 | 否 |
| DELETE | 删除资源 | 是 | 否 |
具体使用示例
http
js
# 获取资源
GET /users/123
# 创建资源
POST /users
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com"
}
# 完整更新资源
PUT /users/123
Content-Type: application/json
{
"name": "John Smith",
"email": "john.smith@example.com"
}
# 部分更新资源
PATCH /users/123
Content-Type: application/json
{
"email": "new.email@example.com"
}
# 删除资源
DELETE /users/123Content-Type(内容类型)与 Accept(接受类型)
| 特性 | Content-Type | Accept |
|---|---|---|
| 方向 | 主要描述请求体格式 | 描述期望的响应格式 |
| 请求中 | 声明客户端发送数据的格式 | 声明客户端希望接收数据的格式 |
| 响应中 | 声明服务器返回数据的格式 | 一般不用于响应 |
| 必需性 | 有请求体时通常必需 | 可选,但有最佳实践价值 |
实际开发中的应用
1. 正确的 API 调用示例
javascript
js
// 前端代码调用 API
async function updateUser(userId, userData) {
const response = await fetch(`/api/users/${userId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json', // 我发送的是 JSON
'Accept': 'application/json' // 我希望接收 JSON
},
body: JSON.stringify(userData)
});
return response.json();
}3. HTTP 状态码使用
2xx 成功
- 200 OK:请求成功
- 201 Created:资源创建成功
- 202 Accepted:请求已接受处理,但尚未完成
- 204 No Content:请求成功,但无返回内容
3xx 重定向
- 301 Moved Permanently:资源已永久移动
- 302 Found:资源临时移动
- 304 Not Modified:资源未修改(缓存相关)
4xx 客户端错误
- 400 Bad Request:请求格式错误
- 401 Unauthorized:需要身份验证
- 403 Forbidden:无权限访问
- 404 Not Found:资源不存在
- 405 Method Not Allowed:HTTP方法不允许
- 409 Conflict:资源状态冲突
- 429 Too Many Requests:请求过于频繁
5xx 服务器错误
- 500 Internal Server Error:服务器内部错误
- 501 Not Implemented:功能未实现
- 503 Service Unavailable:服务不可用
返回JSON格式数据
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。
示例响应体结构:
json
jsonCopy Code{
"status": "success",
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"name": "示例数据"
}
}- status:表示请求的状态(如 success, error)。
- code:HTTP状态码或自定义错误码。
- message:状态消息,用于描述操作的结果或错误原因。
- data:实际返回的数据。
错误处理和标准化错误信息
当出现错误时,应返回清晰的错误信息,帮助开发者快速定位问题。
示例错误响应体:
json
jsonCopy Code{
"status": "error",
"code": 404,
"message": "资源未找到",
"details": "指定的资源ID不存在"
}- details:提供更详细的错误信息,有助于调试。
实际开发中的重要考虑
1. 认证和授权
认证与授权在实际开发中的实现细节,尤其是JWT(JSON Web Token)认证和OAuth 2.0授权。
JWT(JSON Web Token)认证
JWT是一种无状态的令牌认证机制,常用于Web API和微服务。
- 令牌本身就是用户身份和权限的信息,服务端不用存session,直接验证令牌即可。
- 令牌内容是一个经过签名的JSON字符串,通常包括用户ID、角色、过期时间等。
2. 认证流程
步骤一:用户登录,获取JWT令牌
HTTP
http
POST /auth/login
Content-Type: application/json
{
"username": "user@example.com",
"password": "password123"
}- 客户端提交用户名和密码,服务端验证是否正确。
步骤二:服务端返回JWT令牌
JSON
json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}- 令牌内容由三部分组成:Header(头)、Payload(载荷)、Signature(签名)。
- 服务端用密钥对令牌进行签名。
步骤三:客户端保存令牌(通常存localStorage或Cookie)
步骤四:客户端访问受保护接口时,带上令牌
HTTP
GET /users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...- 在请求头加
Authorization: Bearer <token>,服务端验证令牌即可。
3. 服务端如何验证JWT?
- 解析令牌,验证签名是否正确(确保没被伪造)。
- 检查令牌是否过期。
- 从令牌中读取用户信息和权限,决定是否允许访问。
4. JWT的优缺点
优点:
- 无状态,服务端不用保存session,扩展性强。
- 可扩展到微服务、分布式架构。
- 可以直接存放权限、角色等信息,API可以快速做权限判断。
缺点:
- 一旦令牌泄露,别人可以伪造身份。
- 令牌不能主动失效(只能等到过期或用黑名单)。
- 刷新机制要自己实现。
5. 实际开发要点
- 令牌要设置合理的过期时间,比如15分钟~2小时。
- 不要把敏感信息(如密码)放在JWT里。
- 密钥要妥善保管,否则令牌验证就失效了。
- HTTPS必须开启,防止令牌被窃听。
- 注意跨域和CSRF问题,存储方式要选对。
http
js
POST /auth/login
Content-Type: application/json
{
"username": "user@example.com",
"password": "password123"
}
# 响应
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}http
http
GET /users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...