Skip to content

Better API

some rule/advice to design better apis.

  1. 一致性

    • 同样的命名规则(I prefer snake_case)
    • uri命名用统一的单数或复数格式(I like plural)
    • 使用一致的 auth 方案。
    • 使用一致的 headers
    • 使用统一的statuscode,比如404表示未找到。
    • 对于同类操作,使用同样的http-method
  2. ISO8601 UTC时间表示法

    {
        "published_at": "2022-03-03T21:59:08Z"
    }
    
  3. 对于public/private endpoints 进行管理

    • 对于public endpoints 按需要抛出 auth exception
  4. 提供 health check endpoint

    • for example: /health or /ping
  5. 尽早进行API version管理

    • version the api,或者从url,或者parameter, 或者 header
    https://api.life.com/v1/health
    https://api.life.com/health?api_version=1.0
    
  6. 承认 API 的 key auth

    • 自定义 Api-Key 放于header中,同时制定过期机制,以及避免将 key 这种敏感信息放置到源代码中(建议用 environment variables 控制)
  7. 使用通用的HTTP status code

    200 for general success
    201 for successful creation
    400 for bad requests from the client
    401 for unauthorized requests
    403 for missing permissions
    404 for missing resources
    429 for too many requests
    5xx for internal errors (these should be avoided at all costs)
    
  8. 使用通用的 HTTP method

    POST  for creating
    GET   for reading
    PATCH for partial updates
    PUT   for full updates
    DELETE for deleting
    
    # example:
    POST /users
    GET /users
    GET /users/{id}
    PATCH /users/{id}
    PUT /users/{id}
    DELETE /users/{id}
    
  9. 用高效词汇作为URL

    • url面向资源,避免用无关信息等。
    # GOOD:
    GET /users => Retrieve users
    DELETE /users/{id} => Delete a user
    POST /users/{id}/notifications => Create a notification for a specific user
    user.first_name
    order.number
    # BAD:
    GET /getUser
    POST /updateUser
    POST /notification/user
    order.ordernumber
    user.firstName
    
  10. 使用标准的error responses

    // Request => GET /users/4TL011ax
    // Response <= 404 Not Found
    {
        "code": "user/not_found",
        "message": "A user with the ID 4TL011ax could not be found."
    }
    

  11. POST返回创建后的资源

    // Request: POST /users
    {
        "email": "jdoe@averagecompany.com",
        "name": "John Doe"
    }
    
    // Response
    {
        "id": "T9hoBuuTL4",
        "email": "jdoe@averagecompany.com",
        "name": "John Doe"
    }
    
  12. PATCH 优于 PUT

    • 因为整体替换太危险了
  13. 命名尽量specifig

    • 避免给人歧义或者误导用户
  14. 使用分页

    • 尽早规划分页,不论是simple pagination 还是 deep pagination
    // Request => GET /users?page_number=1&page_size=15
    
    // Response <= 200 OK
    {
        "page_number": 1,
        "page_size": 15,
        "count": 378,
        "data": [
            // resources
        ],
        "total_pages": 26,
        "has_previous_page": true,
        "has_next_page": true
    }
    
  15. 允许扩展资源

    • 在很多时候尽量允许使用expand, 一方面避免round-trips, 一方面避免加载所有数据
    // Request => GET /users/T9hoBuuTL4?expand=orders&expand=orders.items
    
    // Response <= 200 OK
    {
    "id": "T9hoBuuTL4",
    "email": "jdoe@averagecompany.com",
    "name": "John Doe",
    "orders": [
        {
        "id": "Hy3SSXU1PF",
        "items": [
            {
            "name": "API course"
            },
            {
            "name": "iPhone 13"
            }
        ]
        },
        {
        "id": "bx1zKmJLI6",
        "items": [
            {
            "name": "SaaS subscription"
            }
        ]
        }
    ]
    }