端点设计 #
什么是端点? #
端点(Endpoint)是 API 的访问入口,是客户端与服务端交互的具体 URL 路径。
text
┌─────────────────────────────────────────────────────────────┐
│ 端点定义 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 端点 = HTTP 方法 + URL 路径 │
│ │
│ 示例: │
│ GET /users │
│ POST /users │
│ GET /users/123 │
│ PUT /users/123 │
│ DELETE /users/123 │
│ │
│ 完整端点示例: │
│ https://api.example.com/v1/users/123 │
│ └──┬───┘ └───────┬───────┘ └┬┘ └────┬────┘ │
│ 协议 域名/主机 版本 资源路径 │
│ │
└─────────────────────────────────────────────────────────────┘
URL 结构设计 #
基础 URL 结构 #
text
┌─────────────────────────────────────────────────────────────┐
│ URL 结构组成 │
├─────────────────────────────────────────────────────────────┤
│ │
│ https://api.example.com/v1/users/123/orders?status=pending │
│ └──┬──┘ └───────┬───────┘└┬┘└─────┬─────┘ └───────┬───────┘│
│ 协议 主机地址 版本 资源路径 查询参数 │
│ │
│ 各部分说明: │
│ │
│ 1. 协议(Scheme) │
│ - 始终使用 HTTPS │
│ - 保证传输安全 │
│ │
│ 2. 主机地址(Host) │
│ - api.example.com │
│ - 建议使用 api 子域名 │
│ │
│ 3. 版本(Version) │
│ - /v1, /v2 │
│ - 便于 API 演进 │
│ │
│ 4. 资源路径(Resource Path) │
│ - /users/123/orders │
│ - 表示资源层级 │
│ │
│ 5. 查询参数(Query String) │
│ - ?status=pending │
│ - 过滤、排序、分页 │
│ │
└─────────────────────────────────────────────────────────────┘
URL 设计规则 #
text
┌─────────────────────────────────────────────────────────────┐
│ URL 设计规则 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 规则一:使用名词表示资源 │
│ ───────────────────────────────────────────── │
│ ✅ GET /users │
│ ❌ GET /getUsers │
│ │
│ 规则二:使用复数形式 │
│ ───────────────────────────────────────────── │
│ ✅ GET /users │
│ ❌ GET /user │
│ │
│ 规则三:使用小写字母 │
│ ───────────────────────────────────────────── │
│ ✅ GET /user-profiles │
│ ❌ GET /UserProfiles │
│ │
│ 规则四:使用连字符分隔单词 │
│ ───────────────────────────────────────────── │
│ ✅ GET /order-items │
│ ❌ GET /orderItems │
│ ❌ GET /order_items │
│ │
│ 规则五:避免文件扩展名 │
│ ───────────────────────────────────────────── │
│ ✅ GET /users/123 │
│ ❌ GET /users/123.json │
│ │
│ 规则六:避免尾部斜杠 │
│ ───────────────────────────────────────────── │
│ ✅ GET /users │
│ ❌ GET /users/ │
│ │
│ 规则七:层级不超过三层 │
│ ───────────────────────────────────────────── │
│ ✅ GET /users/123/orders │
│ ⚠️ GET /users/123/orders/456/items/1 │
│ │
└─────────────────────────────────────────────────────────────┘
CRUD 端点设计 #
标准 CRUD 端点 #
text
┌─────────────────────────────────────────────────────────────┐
│ 标准 CRUD 端点 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 资源:用户(User) │
│ │
│ ┌────────┬──────────────────┬────────────────────────┐ │
│ │ 方法 │ 端点 │ 操作 │ │
│ ├────────┼──────────────────┼────────────────────────┤ │
│ │ GET │ /users │ 获取用户列表 │ │
│ │ POST │ /users │ 创建新用户 │ │
│ │ GET │ /users/{id} │ 获取指定用户 │ │
│ │ PUT │ /users/{id} │ 完整更新用户 │ │
│ │ PATCH │ /users/{id} │ 部分更新用户 │ │
│ │ DELETE │ /users/{id} │ 删除用户 │ │
│ └────────┴──────────────────┴────────────────────────┘ │
│ │
│ 资源:订单(Order)- 子资源 │
│ │
│ ┌────────┬──────────────────────────┬────────────────┐ │
│ │ 方法 │ 端点 │ 操作 │ │
│ ├────────┼──────────────────────────┼────────────────┤ │
│ │ GET │ /users/{id}/orders │ 获取用户订单 │ │
│ │ POST │ /users/{id}/orders │ 创建用户订单 │ │
│ │ GET │ /users/{id}/orders/{oid} │ 获取指定订单 │ │
│ │ PUT │ /users/{id}/orders/{oid} │ 更新订单 │ │
│ │ DELETE │ /users/{id}/orders/{oid} │ 删除订单 │ │
│ └────────┴──────────────────────────┴────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
端点设计示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ 完整端点设计示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户管理 API: │
│ │
│ GET /users │
│ 功能:获取用户列表 │
│ 查询参数:page, limit, sort, status │
│ 响应:200 OK + 用户列表 │
│ │
│ POST /users │
│ 功能:创建用户 │
│ 请求体:用户数据 │
│ 响应:201 Created + Location: /users/{id} │
│ │
│ GET /users/{id} │
│ 功能:获取指定用户 │
│ 响应:200 OK + 用户信息 或 404 Not Found │
│ │
│ PUT /users/{id} │
│ 功能:完整更新用户 │
│ 请求体:完整用户数据 │
│ 响应:200 OK 或 204 No Content │
│ │
│ PATCH /users/{id} │
│ 功能:部分更新用户 │
│ 请求体:部分用户数据 │
│ 响应:200 OK 或 204 No Content │
│ │
│ DELETE /users/{id} │
│ 功能:删除用户 │
│ 响应:204 No Content 或 200 OK │
│ │
│ GET /users/{id}/orders │
│ 功能:获取用户订单列表 │
│ 响应:200 OK + 订单列表 │
│ │
│ GET /users/{id}/profile │
│ 功能:获取用户资料 │
│ 响应:200 OK + 用户资料 │
│ │
└─────────────────────────────────────────────────────────────┘
查询参数设计 #
参数类型 #
text
┌─────────────────────────────────────────────────────────────┐
│ 查询参数类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 过滤参数(Filtering) │
│ ───────────────────────────────────────────── │
│ GET /users?status=active │
│ GET /products?category=electronics&price_min=100 │
│ GET /orders?status=pending&created_after=2025-01-01 │
│ │
│ 2. 排序参数(Sorting) │
│ ───────────────────────────────────────────── │
│ GET /users?sort=created_at 升序 │
│ GET /users?sort=-created_at 降序 │
│ GET /users?sort=name,-created_at 多字段排序 │
│ │
│ 3. 分页参数(Pagination) │
│ ───────────────────────────────────────────── │
│ GET /users?page=1&limit=20 页码分页 │
│ GET /users?offset=0&limit=20 偏移分页 │
│ GET /users?cursor=abc123&limit=20 游标分页 │
│ │
│ 4. 字段选择(Field Selection) │
│ ───────────────────────────────────────────── │
│ GET /users?fields=id,name,email │
│ GET /products?fields=id,name,price │
│ │
│ 5. 搜索参数(Search) │
│ ───────────────────────────────────────────── │
│ GET /users?q=zhang │
│ GET /products?search=iPhone │
│ │
│ 6. 展开参数(Expansion) │
│ ───────────────────────────────────────────── │
│ GET /orders/123?expand=user,items │
│ GET /users/123?embed=orders,profile │
│ │
└─────────────────────────────────────────────────────────────┘
参数命名规范 #
text
┌─────────────────────────────────────────────────────────────┐
│ 参数命名规范 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 规则一:使用 camelCase │
│ ✅ ?createdAt=2025-01-01 │
│ ❌ ?created_at=2025-01-01 │
│ │
│ 规则二:语义清晰 │
│ ✅ ?priceMin=100&priceMax=1000 │
│ ❌ ?pmin=100&pmax=1000 │
│ │
│ 规则三:使用下划线表示范围 │
│ ✅ ?created_after=2025-01-01 │
│ ✅ ?created_before=2025-12-31 │
│ │
│ 规则四:布尔值使用 true/false │
│ ✅ ?isActive=true │
│ ❌ ?isActive=1 │
│ │
│ 规则五:数组使用逗号分隔或重复参数 │
│ ✅ ?ids=1,2,3 │
│ ✅ ?ids=1&ids=2&ids=3 │
│ │
└─────────────────────────────────────────────────────────────┘
常用参数约定 #
text
┌─────────────────────────────────────────────────────────────┐
│ 常用参数约定 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 分页参数: │
│ ┌──────────────┬───────────────────────────────────┐ │
│ │ 参数 │ 说明 │ │
│ ├──────────────┼───────────────────────────────────┤ │
│ │ page │ 页码(从 1 开始) │ │
│ │ limit │ 每页数量 │ │
│ │ offset │ 偏移量(从 0 开始) │ │
│ │ cursor │ 游标(用于游标分页) │ │
│ │ perPage │ 每页数量(替代 limit) │ │
│ └──────────────┴───────────────────────────────────┘ │
│ │
│ 排序参数: │
│ ┌──────────────┬───────────────────────────────────┐ │
│ │ 参数 │ 说明 │ │
│ ├──────────────┼───────────────────────────────────┤ │
│ │ sort │ 排序字段 │ │
│ │ order │ 排序方向(asc/desc) │ │
│ │ sortBy │ 排序字段(替代 sort) │ │
│ └──────────────┴───────────────────────────────────┘ │
│ │
│ 搜索参数: │
│ ┌──────────────┬───────────────────────────────────┐ │
│ │ 参数 │ 说明 │ │
│ ├──────────────┼───────────────────────────────────┤ │
│ │ q │ 搜索关键词 │ │
│ │ search │ 搜索关键词 │ │
│ │ query │ 搜索关键词 │ │
│ └──────────────┴───────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
请求设计 #
请求头设计 #
text
┌─────────────────────────────────────────────────────────────┐
│ 请求头设计 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 标准请求头: │
│ │
│ Content-Type: application/json │
│ 请求体格式 │
│ │
│ Accept: application/json │
│ 期望的响应格式 │
│ │
│ Authorization: Bearer eyJhbGciOiJIUzI1NiIs... │
│ 认证信息 │
│ │
│ Accept-Language: zh-CN │
│ 语言偏好 │
│ │
│ If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT │
│ 缓存验证 │
│ │
│ If-None-Match: "33a64df551425fcc55e4d42a148795d9" │
│ ETag 验证 │
│ │
│ User-Agent: MyApp/1.0 │
│ 客户端标识 │
│ │
│ X-Request-ID: 550e8400-e29b-41d4-a716-446655440000 │
│ 请求追踪 ID │
│ │
└─────────────────────────────────────────────────────────────┘
请求体设计 #
text
┌─────────────────────────────────────────────────────────────┐
│ 请求体设计 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 创建资源(POST): │
│ POST /users │
│ Content-Type: application/json │
│ │
│ { │
│ "name": "张三", │
│ "email": "zhangsan@example.com", │
│ "password": "securePassword123" │
│ } │
│ │
│ 完整更新(PUT): │
│ PUT /users/123 │
│ Content-Type: application/json │
│ │
│ { │
│ "name": "李四", │
│ "email": "lisi@example.com", │
│ "status": "active" │
│ } │
│ │
│ 部分更新(PATCH): │
│ PATCH /users/123 │
│ Content-Type: application/json │
│ │
│ { │
│ "name": "王五" │
│ } │
│ │
│ 批量操作: │
│ POST /users/batch │
│ Content-Type: application/json │
│ │
│ { │
│ "users": [ │
│ { "name": "用户1", "email": "user1@example.com" }, │
│ { "name": "用户2", "email": "user2@example.com" } │
│ ] │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
响应设计 #
响应头设计 #
text
┌─────────────────────────────────────────────────────────────┐
│ 响应头设计 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 标准响应头: │
│ │
│ Content-Type: application/json; charset=utf-8 │
│ 响应体格式 │
│ │
│ Content-Length: 1234 │
│ 响应体长度 │
│ │
│ ETag: "33a64df551425fcc55e4d42a148795d9" │
│ 资源版本标识 │
│ │
│ Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT │
│ 最后修改时间 │
│ │
│ Cache-Control: max-age=3600, public │
│ 缓存控制 │
│ │
│ Location: https://api.example.com/users/123 │
│ 新资源位置(创建成功时) │
│ │
│ X-RateLimit-Limit: 100 │
│ X-RateLimit-Remaining: 95 │
│ X-RateLimit-Reset: 1640995200 │
│ 速率限制信息 │
│ │
│ X-Request-ID: 550e8400-e29b-41d4-a716-446655440000 │
│ 请求追踪 ID │
│ │
└─────────────────────────────────────────────────────────────┘
响应体设计 #
text
┌─────────────────────────────────────────────────────────────┐
│ 响应体设计 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 单个资源响应: │
│ GET /users/123 │
│ │
│ { │
│ "id": 123, │
│ "name": "张三", │
│ "email": "zhangsan@example.com", │
│ "status": "active", │
│ "createdAt": "2025-01-15T10:30:00Z", │
│ "updatedAt": "2025-03-20T15:45:00Z" │
│ } │
│ │
│ 资源列表响应: │
│ GET /users?page=1&limit=20 │
│ │
│ { │
│ "data": [ │
│ { "id": 1, "name": "张三" }, │
│ { "id": 2, "name": "李四" } │
│ ], │
│ "pagination": { │
│ "page": 1, │
│ "limit": 20, │
│ "total": 100, │
│ "totalPages": 5 │
│ } │
│ } │
│ │
│ 创建成功响应: │
│ POST /users │
│ │
│ HTTP/1.1 201 Created │
│ Location: https://api.example.com/users/124 │
│ │
│ { │
│ "id": 124, │
│ "name": "张三", │
│ "email": "zhangsan@example.com", │
│ "createdAt": "2025-03-29T10:30:00Z" │
│ } │
│ │
│ 无内容响应: │
│ DELETE /users/123 │
│ │
│ HTTP/1.1 204 No Content │
│ │
└─────────────────────────────────────────────────────────────┘
分页响应格式 #
text
┌─────────────────────────────────────────────────────────────┐
│ 分页响应格式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 格式一:包含分页元数据 │
│ { │
│ "data": [...], │
│ "pagination": { │
│ "page": 1, │
│ "limit": 20, │
│ "total": 100, │
│ "totalPages": 5 │
│ } │
│ } │
│ │
│ 格式二:包含链接 │
│ { │
│ "data": [...], │
│ "links": { │
│ "first": "/users?page=1", │
│ "prev": null, │
│ "next": "/users?page=2", │
│ "last": "/users?page=5" │
│ }, │
│ "meta": { │
│ "total": 100 │
│ } │
│ } │
│ │
│ 格式三:游标分页 │
│ { │
│ "data": [...], │
│ "cursor": { │
│ "before": "abc123", │
│ "after": "def456" │
│ }, │
│ "hasMore": true │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
特殊端点设计 #
操作端点 #
text
┌─────────────────────────────────────────────────────────────┐
│ 操作端点设计 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 非 CRUD 操作的处理方式: │
│ │
│ 方式一:使用动词作为子资源 │
│ POST /orders/123/cancel 取消订单 │
│ POST /orders/123/confirm 确认订单 │
│ POST /users/123/activate 激活用户 │
│ POST /users/123/deactivate 停用用户 │
│ │
│ 方式二:使用状态变更 │
│ PATCH /orders/123 │
│ { "status": "cancelled" } │
│ │
│ 方式三:使用动作资源 │
│ POST /order-actions │
│ { │
│ "orderId": 123, │
│ "action": "cancel" │
│ } │
│ │
│ 推荐:优先使用方式二(状态变更),语义更清晰 │
│ │
└─────────────────────────────────────────────────────────────┘
批量操作端点 #
text
┌─────────────────────────────────────────────────────────────┐
│ 批量操作端点 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 批量创建: │
│ POST /users/batch │
│ { │
│ "users": [ │
│ { "name": "用户1", "email": "user1@example.com" }, │
│ { "name": "用户2", "email": "user2@example.com" } │
│ ] │
│ } │
│ │
│ 批量更新: │
│ PATCH /users/batch │
│ { │
│ "ids": [1, 2, 3], │
│ "updates": { │
│ "status": "active" │
│ } │
│ } │
│ │
│ 批量删除: │
│ DELETE /users/batch?ids=1,2,3 │
│ 或 │
│ POST /users/batch-delete │
│ { │
│ "ids": [1, 2, 3] │
│ } │
│ │
│ 批量响应: │
│ { │
│ "success": [ │
│ { "id": 1, "status": "created" }, │
│ { "id": 2, "status": "created" } │
│ ], │
│ "failed": [ │
│ { "id": 3, "error": "Email already exists" } │
│ ] │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
搜索端点 #
text
┌─────────────────────────────────────────────────────────────┐
│ 搜索端点设计 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 方式一:资源端点 + 查询参数 │
│ GET /users?q=zhang │
│ GET /products?search=iPhone&category=electronics │
│ │
│ 方式二:专用搜索端点 │
│ GET /search?q=iPhone&type=products │
│ GET /search/users?q=zhang │
│ │
│ 方式三:高级搜索 │
│ POST /search │
│ { │
│ "query": "iPhone", │
│ "filters": { │
│ "category": "electronics", │
│ "priceRange": { │
│ "min": 100, │
│ "max": 1000 │
│ } │
│ }, │
│ "sort": { │
│ "field": "price", │
│ "order": "asc" │
│ } │
│ } │
│ │
│ 搜索响应: │
│ { │
│ "results": [...], │
│ "facets": { │
│ "categories": [ │
│ { "name": "Electronics", "count": 150 }, │
│ { "name": "Accessories", "count": 80 } │
│ ] │
│ }, │
│ "total": 230, │
│ "took": 15 │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
文件上传端点 #
text
┌─────────────────────────────────────────────────────────────┐
│ 文件上传端点 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 单文件上传: │
│ POST /uploads │
│ Content-Type: multipart/form-data │
│ │
│ file: [binary data] │
│ │
│ 响应: │
│ { │
│ "id": "abc123", │
│ "url": "https://cdn.example.com/files/abc123.jpg", │
│ "filename": "photo.jpg", │
│ "mimeType": "image/jpeg", │
│ "size": 102400 │
│ } │
│ │
│ 关联资源的文件上传: │
│ POST /users/123/avatar │
│ Content-Type: multipart/form-data │
│ │
│ file: [binary data] │
│ │
│ 多文件上传: │
│ POST /uploads/batch │
│ Content-Type: multipart/form-data │
│ │
│ files: [binary data 1], [binary data 2] │
│ │
└─────────────────────────────────────────────────────────────┘
端点设计检查清单 #
text
□ URL 设计
□ 使用名词表示资源
□ 使用复数形式
□ 使用小写字母
□ 使用连字符分隔
□ 无文件扩展名
□ 无尾部斜杠
□ 层级不超过三层
□ HTTP 方法
□ GET 用于查询
□ POST 用于创建
□ PUT 用于完整更新
□ PATCH 用于部分更新
□ DELETE 用于删除
□ 查询参数
□ 参数命名规范
□ 支持过滤
□ 支持排序
□ 支持分页
□ 支持字段选择
□ 请求设计
□ 请求头完整
□ 请求体格式正确
□ 认证信息传递
□ 响应设计
□ 状态码正确
□ 响应头完整
□ 响应体格式统一
□ 分页格式规范
下一步 #
现在你已经了解了端点设计的方法,接下来学习 HTTP 方法使用,深入了解各种 HTTP 方法的正确使用方式!
最后更新:2026-03-29