DevToolBox免费
博客

REST API 设计最佳实践:完整指南

12 分钟作者 DevToolBox

设计优秀的 REST API 不仅仅是返回 JSON。一个设计良好的 API 应该是可预测、一致、安全且易于使用的。本指南涵盖最重要的 REST API 设计最佳实践,包括真实案例、常见错误和经过实战检验的模式。

1. 使用名词作为资源 URI

REST API 建模的是资源而不是操作。URI 应该表示事物(名词),而不是操作(动词)。HTTP 方法(GET、POST、PUT、DELETE)已经描述了操作。

# Good - nouns representing resources
GET    /api/v1/users          # list users
GET    /api/v1/users/123      # get user 123
POST   /api/v1/users          # create a user
PUT    /api/v1/users/123      # replace user 123
PATCH  /api/v1/users/123      # partially update user 123
DELETE /api/v1/users/123      # delete user 123

# Bad - verbs describing actions
GET    /api/v1/getUsers
POST   /api/v1/createUser
POST   /api/v1/deleteUser/123
GET    /api/v1/getUserById?id=123
# Nested resources (one level deep)
GET    /api/v1/users/123/orders       # orders for user 123
GET    /api/v1/users/123/orders/456   # order 456 for user 123
POST   /api/v1/users/123/orders       # create order for user 123

# For actions that don't map to CRUD, use sub-resources
POST   /api/v1/users/123/activate     # activate user (action)
POST   /api/v1/orders/456/cancel      # cancel order (action)
POST   /api/v1/emails/789/resend      # resend email

2. 正确使用 HTTP 方法

每个 HTTP 方法都有特定的语义。使用正确的方法使 API 可预测,并支持缓存、幂等性和浏览器集成。

MethodPurposeIdempotentRequest Body
GETRead a resourceYesNo
POSTCreate a resourceNoYes
PUTFull replacementYesYes
PATCHPartial updateNo*Yes
DELETERemove a resourceYesNo

3. 使用复数资源名称

始终使用复数名词作为集合名。无论访问集合还是单个资源,URI 都保持一致。

# Good - consistent plural nouns
/api/v1/users
/api/v1/users/123
/api/v1/products
/api/v1/products/456/reviews

# Bad - mixing singular and plural
/api/v1/user          # singular
/api/v1/user/123
/api/v1/productList   # avoid "list" suffix

4. 正确使用 HTTP 状态码

状态码告诉客户端发生了什么,无需解析响应体。最重要的三个范围是 2xx(成功)、4xx(客户端错误)和 5xx(服务器错误)。

CodeWhen to Use
200 OKSuccessful GET, PUT, PATCH, or DELETE
201 CreatedSuccessful POST that creates a resource
204 No ContentSuccessful DELETE with no response body
400 Bad RequestMalformed request syntax or invalid data
401 UnauthorizedMissing or invalid authentication
403 ForbiddenAuthenticated but not authorized
404 Not FoundResource does not exist
409 ConflictConflicting state (e.g., duplicate email)
422 UnprocessableValidation errors in request body
429 Too Many RequestsRate limit exceeded
500 Internal ErrorUnexpected server error

5. API 版本控制

API 版本控制在你进行破坏性变更时保护现有消费者。有三种常见策略,各有取舍。

# Strategy 1: URI versioning (most common)
GET /api/v1/users
GET /api/v2/users

# Strategy 2: Header versioning
GET /api/users
Accept: application/vnd.myapi.v2+json

# Strategy 3: Query parameter versioning
GET /api/users?version=2
StrategyProsCons
URI pathSimple, visible, cacheableURI pollution
HeaderClean URIsHarder to test, less visible
Query paramEasy to addCache-unfriendly, easy to forget

6. 分页、过滤和排序

任何返回集合的端点都应支持分页。否则响应会无限增长,服务器和客户端的性能都会下降。

# Offset-based pagination (simplest)
GET /api/v1/users?page=2&limit=25
GET /api/v1/users?offset=25&limit=25

# Cursor-based pagination (better for large datasets)
GET /api/v1/users?cursor=eyJpZCI6MTAwfQ&limit=25

# Response with pagination metadata
{
  "data": [...],
  "pagination": {
    "total": 1250,
    "page": 2,
    "limit": 25,
    "totalPages": 50,
    "hasNext": true,
    "hasPrev": true
  }
}

# Filtering and sorting
GET /api/v1/products?category=electronics&minPrice=100&maxPrice=500
GET /api/v1/products?sort=price&order=asc
GET /api/v1/products?sort=-created_at  # prefix with - for descending
GET /api/v1/users?fields=id,name,email  # sparse fieldsets

7. 错误响应格式

整个 API 一致的错误响应格式有助于客户端以编程方式处理错误。包含错误代码、人类可读消息和验证错误的字段级详情。

// Consistent error response format
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address",
        "value": "not-an-email"
      },
      {
        "field": "age",
        "message": "Must be at least 18",
        "value": 15
      }
    ],
    "requestId": "req_abc123",
    "timestamp": "2026-01-15T10:30:00Z",
    "docs": "https://api.example.com/docs/errors#VALIDATION_ERROR"
  }
}

// Simple error (non-validation)
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "User with id 999 not found",
    "requestId": "req_def456"
  }
}

8. 认证与安全

API 安全性不可妥协。以下是每个 API 从第一天起就应实施的基本安全实践。

# Bearer token authentication (JWT)
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

# API key authentication
GET /api/v1/users
X-API-Key: sk_live_abc123def456

# OAuth 2.0 token request
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=read:users write:users
  • Always use HTTPS in production
  • Never put secrets in query parameters (they appear in server logs)
  • Use short-lived access tokens (15-60 min) with refresh tokens
  • Implement CORS properly for browser-based clients
  • Validate and sanitize all input to prevent injection attacks
  • Use rate limiting to prevent brute-force attacks

9. 速率限制

速率限制保护 API 免受滥用,并确保客户端之间的公平使用。始终通过标准 HTTP 头通知限制信息。

# Rate limit response headers (standard)
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000        # max requests per window
X-RateLimit-Remaining: 742     # requests remaining
X-RateLimit-Reset: 1706810400  # Unix timestamp when limit resets
Retry-After: 60                # seconds until next request (on 429)

# Rate limit exceeded response
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Limit: 1000/hour",
    "retryAfter": 60
  }
}

10. HATEOAS 和链接

超媒体作为应用程序状态引擎(HATEOAS)通过在响应中包含链接来增加 API 的可发现性。

// HATEOAS response example
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com",
  "status": "active",
  "_links": {
    "self": { "href": "/api/v1/users/123" },
    "orders": { "href": "/api/v1/users/123/orders" },
    "deactivate": {
      "href": "/api/v1/users/123/deactivate",
      "method": "POST"
    }
  }
}

// Paginated collection with HATEOAS links
{
  "data": [...],
  "_links": {
    "self": { "href": "/api/v1/users?page=2&limit=25" },
    "first": { "href": "/api/v1/users?page=1&limit=25" },
    "prev": { "href": "/api/v1/users?page=1&limit=25" },
    "next": { "href": "/api/v1/users?page=3&limit=25" },
    "last": { "href": "/api/v1/users?page=50&limit=25" }
  }
}

常见问题

更新应该用 PUT 还是 PATCH?

PUT 用于完整替换资源,PATCH 用于部分更新。大多数现代 API 更倾向使用 PATCH。

REST API URI 应该小写吗?

是的,URI 应该使用小写加连字符(kebab-case)。JSON 属性名使用 camelCase。

如何处理嵌套资源?

限制嵌套在一层以内。深度嵌套的资源应该提升为顶级端点并使用查询参数。

REST API 最佳认证方式是什么?

服务器间通信用 API 密钥或 OAuth 2.0。面向用户的应用使用 OAuth 2.0 和 JWT。始终使用 HTTPS。

应该用 GraphQL 替代 REST 吗?

REST 和 GraphQL 解决不同问题。REST 更简单,缓存更好。GraphQL 适合复杂数据需求。很多团队两者结合使用。

TL;DR

  • Use nouns (not verbs) for resource URIs
  • Use the correct HTTP method for each operation
  • Always use plural resource names
  • Return appropriate HTTP status codes
  • Version your API from day one (URI path is simplest)
  • Support pagination, filtering, and sorting for collections
  • Use a consistent error response format
  • Always use HTTPS and proper authentication
  • Implement rate limiting with standard headers
  • Consider HATEOAS for API discoverability

从一开始就遵循这些最佳实践,可以节省大量重构时间。使用我们的工具来测试和验证 API 响应。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

{ }JSON Formatter4xxHTTP Status Code ReferenceJWTJWT Decoder

相关文章

REST API 最佳实践:2026 完整指南

学习 REST API 设计最佳实践,包括命名规范、错误处理、认证、分页、版本控制和安全头。

HTTP 状态码:开发者完全参考指南

完整的 HTTP 状态码参考:1xx 到 5xx,包含实用解释、API 最佳实践和常见调试技巧。

API 认证:OAuth 2.0 vs JWT vs API Key

比较 API 认证方式:OAuth 2.0、JWT Bearer Token 和 API Key。了解每种方式的适用场景、安全权衡和实现模式。