Skip to content
ADP
API Design PrincipleBETA

[ADP-130] 冪等性金鑰(Idempotency-Key)

概述

POST/PATCH 請求在本質上並非冪等的,但我們可以透過使用 Idempotency-Key 標頭,使得 POST/PATCH 請求具有冪等性,從而確保多次發送相同的請求與單次發送請求具有相同的結果。這樣,客戶端可以安全地重試請求,不會產生意外的副作用。有關冪等的更多信息,請參考ADP-366

指導原則

  • API 應該(SHOULD)允許客戶端使用在 POST/PATCH 操作上使用 Idempotency-Key (冪等性金鑰),以確保多個相同請求只被處理一次。

    • 也就是說,API 設計可以(MAY)決定 Idempotency-Key 為可選參數或必要參數。
  • 伺服器必須(MUST)驗證客戶端提供的冪等性金鑰對每個請求都是唯一的,以防止重複處理。

  • 如 RFC 草案所建議,使用 UUID 可以確保冪等性金鑰具有高度的唯一性和隨機性。

  • 客戶端可以(MAY)決定是否在請求標頭中包含冪等性金鑰。對於因網絡問題而失敗的請求,客戶端可以使用相同的冪等性金鑰重試。

  • 如果 API 要求冪等性金鑰,當金鑰缺失時,應該(SHOULD)回應 400 Bad Request。

  • 如果冪等性金鑰不是強制性的,API 仍應(SHOULD)處理非冪等操作的請求。

實現示例

場景

客戶端使用 POST 請求創建新資源,包含冪等性金鑰以防止重試時多次創建資源。

請求

http
POST /resources HTTP/1.1
Host: api.example.com
Idempotency-Key: 123e4567-e89b-12d3-a456-426614174000
Content-Type: application/json
{
  "name": "示例資源",
  "type": "示例"
}

OpenAPI 示例

yaml
openapi: 3.1.0
info:
  title: Example API
  version: 1.0.0
paths:
  /resources:
    post:
      summary: Create a new resource
      operationId: createResource
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                type:
                  type: string
              required:
                - name
                - type
      responses:
        '201':
          description: Resource created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
                  type:
                    type: string
        '400':
          description: Idempotency-Key is missing
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
          description: A unique identifier to ensure idempotency

components:
  schemas:
    Error:
      type: object
      properties:
        type:
          type: string
        title:
          type: string
        detail:
          type: string

參考