rest-api-designer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

REST API Designer

REST API 设计器

Design RESTful APIs with proper resource modeling and endpoint structure.
通过合理的资源建模和端点结构来设计RESTful API。

Quick Start

快速入门

Use resource-based URLs with plural nouns, proper HTTP methods, and consistent patterns.
使用基于资源的URL,采用复数名词、正确的HTTP方法以及一致的格式。

Instructions

操作指南

Core REST Principles

REST核心原则

Resources, not actions:
Good: GET /users, POST /users
Bad: GET /getUsers, POST /createUser
Use HTTP methods correctly:
  • GET: Retrieve (safe, idempotent)
  • POST: Create (not idempotent)
  • PUT: Replace (idempotent)
  • PATCH: Partial update (not idempotent)
  • DELETE: Remove (idempotent)
Use plural nouns:
Good: /products, /orders
Bad: /product, /order
资源优先,而非操作:
Good: GET /users, POST /users
Bad: GET /getUsers, POST /createUser
正确使用HTTP方法:
  • GET:检索资源(安全、幂等)
  • POST:创建资源(非幂等)
  • PUT:替换资源(幂等)
  • PATCH:部分更新(非幂等)
  • DELETE:删除资源(幂等)
使用复数名词:
Good: /products, /orders
Bad: /product, /order

Resource Modeling

资源建模

Identify resources:
  1. List main entities (users, products, orders)
  2. Identify relationships (user has orders, order has items)
  3. Determine hierarchies (posts have comments)
Design URL structure:
/api/v1/resources
/api/v1/resources/{id}
/api/v1/resources/{id}/sub-resources
Example - Blog API:
GET    /api/v1/posts           # List posts
POST   /api/v1/posts           # Create post
GET    /api/v1/posts/{id}      # Get post
PUT    /api/v1/posts/{id}      # Replace post
PATCH  /api/v1/posts/{id}      # Update post
DELETE /api/v1/posts/{id}      # Delete post

GET    /api/v1/posts/{id}/comments    # List comments
POST   /api/v1/posts/{id}/comments    # Create comment
识别资源:
  1. 列出主要实体(用户、产品、订单)
  2. 明确关联关系(用户拥有订单,订单包含商品)
  3. 确定层级结构(帖子包含评论)
设计URL结构:
/api/v1/resources
/api/v1/resources/{id}
/api/v1/resources/{id}/sub-resources
示例 - 博客API:
GET    /api/v1/posts           # 列出帖子
POST   /api/v1/posts           # 创建帖子
GET    /api/v1/posts/{id}      # 获取单个帖子
PUT    /api/v1/posts/{id}      # 替换帖子
PATCH  /api/v1/posts/{id}      # 更新帖子
DELETE /api/v1/posts/{id}      # 删除帖子

GET    /api/v1/posts/{id}/comments    # 列出评论
POST   /api/v1/posts/{id}/comments    # 创建评论

HTTP Methods

HTTP方法详解

GET - Retrieve resources:
GET /api/v1/users           # List all users
GET /api/v1/users/{id}      # Get specific user
GET /api/v1/users?role=admin # Filter users
Response:
json
{
  "data": [
    { "id": 1, "name": "John" }
  ],
  "meta": {
    "total": 100,
    "page": 1
  }
}
POST - Create resources:
POST /api/v1/users
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john@example.com"
}
Response (201 Created):
json
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com",
  "created_at": "2024-01-01T00:00:00Z"
}
PUT - Replace resource:
PUT /api/v1/users/{id}
Content-Type: application/json

{
  "name": "John Smith",
  "email": "john.smith@example.com"
}
PATCH - Partial update:
PATCH /api/v1/users/{id}
Content-Type: application/json

{
  "email": "newemail@example.com"
}
DELETE - Remove resource:
DELETE /api/v1/users/{id}
Response (204 No Content or 200 with confirmation)
GET - 检索资源:
GET /api/v1/users           # 列出所有用户
GET /api/v1/users/{id}      # 获取指定用户
GET /api/v1/users?role=admin # 筛选管理员用户
响应示例:
json
{
  "data": [
    { "id": 1, "name": "John" }
  ],
  "meta": {
    "total": 100,
    "page": 1
  }
}
POST - 创建资源:
POST /api/v1/users
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john@example.com"
}
响应(201 Created):
json
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com",
  "created_at": "2024-01-01T00:00:00Z"
}
PUT - 替换资源:
PUT /api/v1/users/{id}
Content-Type: application/json

{
  "name": "John Smith",
  "email": "john.smith@example.com"
}
PATCH - 部分更新:
PATCH /api/v1/users/{id}
Content-Type: application/json

{
  "email": "newemail@example.com"
}
DELETE - 删除资源:
DELETE /api/v1/users/{id}
响应(204 No Content 或 200 带确认信息)

Query Parameters

查询参数

Filtering:
GET /api/v1/products?category=electronics&price_min=100
Sorting:
GET /api/v1/products?sort=price&order=desc
GET /api/v1/products?sort=-price  # Descending
Pagination:
GET /api/v1/products?page=2&per_page=20
GET /api/v1/products?offset=20&limit=20
Field selection:
GET /api/v1/users?fields=id,name,email
Search:
GET /api/v1/products?q=laptop
筛选:
GET /api/v1/products?category=electronics&price_min=100
排序:
GET /api/v1/products?sort=price&order=desc
GET /api/v1/products?sort=-price  # 降序
分页:
GET /api/v1/products?page=2&per_page=20
GET /api/v1/products?offset=20&limit=20
字段选择:
GET /api/v1/users?fields=id,name,email
搜索:
GET /api/v1/products?q=laptop

Nested Resources

嵌套资源

One level (recommended):
GET /api/v1/users/{id}/orders
POST /api/v1/users/{id}/orders
Avoid deep nesting:
Bad: /api/v1/users/{id}/orders/{id}/items/{id}/reviews
Better: /api/v1/reviews?item_id={id}
Alternative - flat with filters:
GET /api/v1/orders?user_id={id}
GET /api/v1/comments?post_id={id}
推荐单层嵌套:
GET /api/v1/users/{id}/orders
POST /api/v1/users/{id}/orders
避免深层嵌套:
Bad: /api/v1/users/{id}/orders/{id}/items/{id}/reviews
Better: /api/v1/reviews?item_id={id}
替代方案 - 扁平化加筛选:
GET /api/v1/orders?user_id={id}
GET /api/v1/comments?post_id={id}

Response Format

响应格式

Success response:
json
{
  "data": {
    "id": 1,
    "name": "Product"
  },
  "meta": {
    "timestamp": "2024-01-01T00:00:00Z"
  }
}
List response:
json
{
  "data": [
    { "id": 1, "name": "Item 1" },
    { "id": 2, "name": "Item 2" }
  ],
  "meta": {
    "total": 100,
    "page": 1,
    "per_page": 20
  },
  "links": {
    "self": "/api/v1/items?page=1",
    "next": "/api/v1/items?page=2",
    "prev": null
  }
}
Error response:
json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format"
      }
    ]
  }
}
成功响应:
json
{
  "data": {
    "id": 1,
    "name": "Product"
  },
  "meta": {
    "timestamp": "2024-01-01T00:00:00Z"
  }
}
列表响应:
json
{
  "data": [
    { "id": 1, "name": "Item 1" },
    { "id": 2, "name": "Item 2" }
  ],
  "meta": {
    "total": 100,
    "page": 1,
    "per_page": 20
  },
  "links": {
    "self": "/api/v1/items?page=1",
    "next": "/api/v1/items?page=2",
    "prev": null
  }
}
错误响应:
json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format"
      }
    ]
  }
}

Status Codes

状态码

Success:
  • 200 OK: Successful GET, PUT, PATCH, DELETE
  • 201 Created: Successful POST
  • 204 No Content: Successful DELETE with no response body
Client errors:
  • 400 Bad Request: Invalid input
  • 401 Unauthorized: Missing/invalid auth
  • 403 Forbidden: Insufficient permissions
  • 404 Not Found: Resource doesn't exist
  • 409 Conflict: Resource conflict
  • 422 Unprocessable Entity: Validation error
Server errors:
  • 500 Internal Server Error: Server error
  • 503 Service Unavailable: Temporary unavailability
成功状态:
  • 200 OK:GET、PUT、PATCH、DELETE请求成功
  • 201 Created:POST请求成功
  • 204 No Content:DELETE请求成功且无响应体
客户端错误:
  • 400 Bad Request:输入无效
  • 401 Unauthorized:缺少/无效的身份验证
  • 403 Forbidden:权限不足
  • 404 Not Found:资源不存在
  • 409 Conflict:资源冲突
  • 422 Unprocessable Entity:验证错误
服务端错误:
  • 500 Internal Server Error:服务端内部错误
  • 503 Service Unavailable:服务暂时不可用

Versioning

版本控制

URL versioning (recommended):
/api/v1/users
/api/v2/users
Header versioning:
GET /api/users
Accept: application/vnd.myapi.v1+json
Query parameter:
GET /api/users?version=1
推荐URL版本控制:
/api/v1/users
/api/v2/users
请求头版本控制:
GET /api/users
Accept: application/vnd.myapi.v1+json
查询参数版本控制:
GET /api/users?version=1

Authentication

身份验证

JWT Bearer token:
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
API Key:
GET /api/v1/users
X-API-Key: your-api-key-here
Basic Auth:
GET /api/v1/users
Authorization: Basic base64(username:password)
JWT Bearer令牌:
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
API密钥:
GET /api/v1/users
X-API-Key: your-api-key-here
基础认证:
GET /api/v1/users
Authorization: Basic base64(username:password)

Rate Limiting

速率限制

Include headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200
Response when exceeded (429):
json
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests",
    "retry_after": 60
  }
}
响应头包含限制信息:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200
超出限制时的响应(429):
json
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests",
    "retry_after": 60
  }
}

HATEOAS (Optional)

HATEOAS(可选)

Include links to related resources:
json
{
  "id": 1,
  "name": "Product",
  "links": {
    "self": "/api/v1/products/1",
    "category": "/api/v1/categories/5",
    "reviews": "/api/v1/products/1/reviews"
  }
}
包含关联资源的链接:
json
{
  "id": 1,
  "name": "Product",
  "links": {
    "self": "/api/v1/products/1",
    "category": "/api/v1/categories/5",
    "reviews": "/api/v1/products/1/reviews"
  }
}

Common Patterns

常见模式

Bulk Operations

批量操作

Bulk create:
POST /api/v1/users/bulk
Content-Type: application/json

{
  "users": [
    { "name": "User 1" },
    { "name": "User 2" }
  ]
}
Bulk update:
PATCH /api/v1/users/bulk
Content-Type: application/json

{
  "updates": [
    { "id": 1, "status": "active" },
    { "id": 2, "status": "inactive" }
  ]
}
批量创建:
POST /api/v1/users/bulk
Content-Type: application/json

{
  "users": [
    { "name": "User 1" },
    { "name": "User 2" }
  ]
}
批量更新:
PATCH /api/v1/users/bulk
Content-Type: application/json

{
  "updates": [
    { "id": 1, "status": "active" },
    { "id": 2, "status": "inactive" }
  ]
}

Async Operations

异步操作

Long-running operation:
POST /api/v1/reports
Response: 202 Accepted

{
  "job_id": "abc123",
  "status": "processing",
  "status_url": "/api/v1/jobs/abc123"
}
Check status:
GET /api/v1/jobs/abc123

{
  "status": "completed",
  "result_url": "/api/v1/reports/xyz789"
}
长时间运行的操作:
POST /api/v1/reports
Response: 202 Accepted

{
  "job_id": "abc123",
  "status": "processing",
  "status_url": "/api/v1/jobs/abc123"
}
检查状态:
GET /api/v1/jobs/abc123

{
  "status": "completed",
  "result_url": "/api/v1/reports/xyz789"
}

File Upload

文件上传

Single file:
POST /api/v1/files
Content-Type: multipart/form-data

file: [binary data]
With metadata:
POST /api/v1/documents
Content-Type: multipart/form-data

file: [binary data]
title: "Document Title"
category: "reports"
单个文件:
POST /api/v1/files
Content-Type: multipart/form-data

file: [binary data]
带元数据:
POST /api/v1/documents
Content-Type: multipart/form-data

file: [binary data]
title: "Document Title"
category: "reports"

Webhooks

Webhooks

Register webhook:
POST /api/v1/webhooks

{
  "url": "https://example.com/webhook",
  "events": ["order.created", "order.updated"]
}
注册Webhook:
POST /api/v1/webhooks

{
  "url": "https://example.com/webhook",
  "events": ["order.created", "order.updated"]
}

Health Check

健康检查

GET /api/health

{
  "status": "healthy",
  "version": "1.0.0",
  "timestamp": "2024-01-01T00:00:00Z"
}
GET /api/health

{
  "status": "healthy",
  "version": "1.0.0",
  "timestamp": "2024-01-01T00:00:00Z"
}

Example API Design

API设计示例

E-commerce API

电商API

Products:
GET    /api/v1/products
POST   /api/v1/products
GET    /api/v1/products/{id}
PUT    /api/v1/products/{id}
DELETE /api/v1/products/{id}
GET    /api/v1/products/{id}/reviews
Orders:
GET    /api/v1/orders
POST   /api/v1/orders
GET    /api/v1/orders/{id}
PATCH  /api/v1/orders/{id}
GET    /api/v1/orders/{id}/items
Customers:
GET    /api/v1/customers
POST   /api/v1/customers
GET    /api/v1/customers/{id}
GET    /api/v1/customers/{id}/orders
Cart:
GET    /api/v1/cart
POST   /api/v1/cart/items
DELETE /api/v1/cart/items/{id}
POST   /api/v1/cart/checkout
产品模块:
GET    /api/v1/products
POST   /api/v1/products
GET    /api/v1/products/{id}
PUT    /api/v1/products/{id}
DELETE /api/v1/products/{id}
GET    /api/v1/products/{id}/reviews
订单模块:
GET    /api/v1/orders
POST   /api/v1/orders
GET    /api/v1/orders/{id}
PATCH  /api/v1/orders/{id}
GET    /api/v1/orders/{id}/items
客户模块:
GET    /api/v1/customers
POST   /api/v1/customers
GET    /api/v1/customers/{id}
GET    /api/v1/customers/{id}/orders
购物车模块:
GET    /api/v1/cart
POST   /api/v1/cart/items
DELETE /api/v1/cart/items/{id}
POST   /api/v1/cart/checkout

Best Practices

最佳实践

Use consistent naming:
  • Lowercase URLs
  • Hyphens for multi-word resources:
    /order-items
  • Consistent date formats: ISO 8601
Include metadata:
  • Timestamps (created_at, updated_at)
  • Pagination info
  • API version
Validate input:
  • Check required fields
  • Validate formats
  • Sanitize data
Handle errors gracefully:
  • Clear error messages
  • Appropriate status codes
  • Include error codes for client handling
Document everything:
  • Use OpenAPI/Swagger
  • Include examples
  • Document rate limits
使用一致的命名规范:
  • URL全部小写
  • 多词资源使用连字符:
    /order-items
  • 日期格式保持一致:ISO 8601
包含元数据:
  • 时间戳(created_at、updated_at)
  • 分页信息
  • API版本
验证输入:
  • 检查必填字段
  • 验证格式
  • 清理数据
优雅处理错误:
  • 清晰的错误信息
  • 合适的状态码
  • 提供便于客户端处理的错误码
完整文档:
  • 使用OpenAPI/Swagger
  • 包含示例
  • 文档说明速率限制

Troubleshooting

故障排查

Unclear resource boundaries:
  • Focus on nouns, not verbs
  • Think about data entities
  • Consider client needs
Deep nesting:
  • Limit to one level
  • Use query parameters for filtering
  • Create separate endpoints
Inconsistent responses:
  • Use response templates
  • Standardize error format
  • Document response structure
资源边界不清晰:
  • 聚焦名词而非动词
  • 从数据实体角度思考
  • 考虑客户端需求
深层嵌套:
  • 限制为单层嵌套
  • 使用查询参数筛选
  • 创建独立端点
响应不一致:
  • 使用响应模板
  • 统一错误格式
  • 文档化响应结构