REST(Representational State Transfer)是目前最主流的 API 设计风格。 一个好的 RESTful API 设计能让前后端协作更加顺畅,降低沟通成本和维护难度。 本文将系统介绍 RESTful API 的设计原则与最佳实践。
资源命名规范
REST 的核心思想是把一切视为资源。URL 应该表示资源,而非操作:
# ✅ 好的设计:名词复数 + 层级关系
GET /api/v1/articles # 文章列表
GET /api/v1/articles/123 # 单篇文章
POST /api/v1/articles # 创建文章
PUT /api/v1/articles/123 # 更新文章(全量)
PATCH /api/v1/articles/123 # 更新文章(部分)
DELETE /api/v1/articles/123 # 删除文章
# 子资源
GET /api/v1/articles/123/comments # 文章下的评论
GET /api/v1/articles/123/comments/45 # 特定评论
# ❌ 避免的设计
GET /api/v1/getArticles # 动词
GET /api/v1/article_list # 下划线
POST /api/v1/createArticle # 动词
HTTP 方法与语义
| 方法 | 语义 | 幂等 | 安全 |
|---|---|---|---|
| GET | 获取资源 | 是 | 是 |
| POST | 创建资源 | 否 | 否 |
| PUT | 全量更新 | 是 | 否 |
| PATCH | 部分更新 | 否 | 否 |
| DELETE | 删除资源 | 是 | 否 |
HTTP 状态码
# 2xx — 成功
200 OK # 请求成功(GET、PUT、PATCH)
201 Created # 创建成功(POST)
204 No Content # 删除成功,无响应体
# 3xx — 重定向
301 Moved Permanently # 资源永久迁移
304 Not Modified # 缓存有效
# 4xx — 客户端错误
400 Bad Request # 请求参数有误
401 Unauthorized # 未认证
403 Forbidden # 无权限
404 Not Found # 资源不存在
409 Conflict # 资源冲突
422 Unprocessable # 语义错误(参数校验失败)
429 Too Many Requests # 被限流
# 5xx — 服务端错误
500 Internal Server Error # 服务端内部错误
502 Bad Gateway # 网关错误
503 Service Unavailable # 服务不可用
分页、过滤与排序
# 分页(推荐游标分页,避免 offset 在大数据量下的性能问题)
GET /api/v1/articles?cursor=123&limit=20
# 传统页码分页
GET /api/v1/articles?page=2&page_size=20
# 过滤
GET /api/v1/articles?status=published&category=backend
# 排序
GET /api/v1/articles?sort=-created_at,+title # - 表示降序
# 字段选择(减少传输量)
GET /api/v1/articles?fields=id,title,created_at
统一响应格式
// 成功响应
{
"code": 0,
"message": "success",
"data": {
"id": 123,
"title": "RESTful API 设计",
"created_at": "2026-07-04T10:30:00Z"
}
}
// 列表响应
{
"code": 0,
"message": "success",
"data": {
"items": [...],
"total": 100,
"next_cursor": "abc123"
}
}
// 错误响应
{
"code": 40401,
"message": "文章不存在",
"details": {
"resource": "article",
"id": "999"
}
}
版本控制
# 推荐:URL 路径版本(简单直观)
/api/v1/articles
/api/v2/articles
# 备选:请求头版本(URL 更干净,但调试不便)
GET /api/articles
Accept: application/vnd.myapp.v2+json
# 版本更新原则:
# - 新增字段:不需要升版本,向后兼容
# - 删除/重命名字段:需要新版本
# - 改变字段语义:需要新版本
认证与安全
# JWT 认证
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
# API 限流响应头
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1699000000
# CORS 配置(仅信任可信域名)
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
HATEOAS:让 API 自描述
// 在响应中包含相关操作的链接
{
"id": 123,
"title": "RESTful API 设计",
"status": "draft",
"_links": {
"self": { "href": "/api/v1/articles/123" },
"comments": { "href": "/api/v1/articles/123/comments" },
"publish": { "href": "/api/v1/articles/123/publish", "method": "POST" },
"author": { "href": "/api/v1/users/42" }
}
}
实战:用 FastAPI 实现 RESTful API
from fastapi import FastAPI, Query, Path, HTTPException
from pydantic import BaseModel
from typing import Optional
app = FastAPI(title="Blog API", version="1.0.0")
class ArticleCreate(BaseModel):
title: str
content: str
category: str
class ArticleResponse(BaseModel):
id: int
title: str
content: str
category: str
created_at: str
@app.get("/api/v1/articles", response_model=list[ArticleResponse])
async def list_articles(
category: Optional[str] = None,
cursor: Optional[int] = None,
limit: int = Query(default=20, le=100)
):
# 查询逻辑
return []
@app.post("/api/v1/articles", status_code=201)
async def create_article(body: ArticleCreate):
# 创建逻辑
return {"id": 123, **body.dict()}
@app.get("/api/v1/articles/{article_id}")
async def get_article(
article_id: int = Path(ge=1)
):
# 查询逻辑
raise HTTPException(status_code=404, detail="文章不存在")
总结
好的 API 设计遵循一致性原则,让调用方能够"猜"到下一个接口的用法。 核心要点:资源命名用名词复数、正确使用 HTTP 方法和状态码、 提供统一响应格式和分页机制、做好版本控制和认证。 RESTful API 不是银弹——对于实时通信等场景,可能需要结合 WebSocket 或 GraphQL。
← 返回首页