Skip to content
ADP
API Design PrincipleBETA

[ADP-137] Range

概述

HTTP 中的 Range 標頭允許客戶端請求資源的特定部分,而不是整個資源。這對於有效處理大型數據集、提供部分回應和支持可恢復下載非常有用。雖然主要用於字節範圍,但在 RESTful API 中也可以適用於其他單位,如項目或記錄。然而,為確保正確實現和客戶端-服務器交互,需要仔細的文件說明和遵守標準。

指導

  • 不應(SHOULD NOT)用 Range 標頭進行分頁。請參考 ADP-312: 分頁了解首選做法。

    • 如果必須使用基於 Range 的分頁,請清楚說明所使用的單位。

    • 基於 Range 的分頁示例:

      ```http
      GET /users
      Range: users=0-9
      
      206 Partial Content
      Accept-Ranges: users
      Content-Range: users 0-9/200
      ```
      
    • 在上面的例子中,單位是 users。它應該是資源/實體類型的複數形式。

  • 對於更複雜的用例,Range 標頭可以(MAY)指定字節範圍,詳見 RFC 9110 規範。

    • 字節範圍值示例:

      ```
      bytes=-500
      bytes=9500-
      bytes=0-0,-1
      bytes=0-999,4500-5499,-1000
      ```
      
  • 如果無法滿足請求的 Range 或不支持指定的單位,服務器應(SHOULD)回應 HTTP 狀態 416(Range Not Satisfiable)。

    • 使用 HTTP Problem Details(RFC 9457)提供更多錯誤資訊。

      ```http
      GET /images/{image-id} HTTP/1.1
      Range: bytes=500-509
      
      HTTP/1.1 416 Range Not Satisfiable
      Content-Type: application/problem+json
      Content-Range: */200
      {
        "type": "/problems/range-not-satisfiable",
        "title": "Range Not Satisfiable",
        "status": 416,
        "detail": "無法滿足請求的範圍",
        "instance": "/images/{image-id}"
      }
      ```
      

示例

考慮一個用於檢索大文件部分內容的 API 端點。以下是如何實現 Range 標頭進行部分內容檢索:

http
GET /largefile HTTP/1.1
Range: bytes=0-999
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 0-999/5000

如果客戶端請求無法滿足的範圍:

http
GET /largefile
Range: bytes=6000-6999
HTTP/1.1 416 Range Not Satisfiable
Content-Type: application/problem+json
Content-Range: /5000
{
  "type": "https://example.com/problems/range-not-satisfiable",
  "title": "Range Not Satisfiable",
  "status": 416,
  "detail": "無法滿足請求的範圍",
  "instance": "/largefile"
}

OpenAPI 示例

要在 OpenAPI 規範中記錄 Range 標頭的使用,可以使用以下示例:

yaml
openapi: 3.1.0
info:
  title: Large File API
  version: 1.0.0
paths:
  /largefile:
    get:
      summary: Retrieve a range of bytes from a large file
      parameters:
        - name: Range
          in: header
          required: false
          schema:
            type: string
            example: bytes=0-999
          description: Range header to request a specific range of bytes.
      responses:
        '206':
          description: Partial Content
          headers:
            Accept-Ranges:
              description: Supported units for the Range header
              schema:
                type: string
            Content-Range:
              description: The range of bytes returned
              schema:
                type: string
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        '416':
          description: Range Not Satisfiable
          headers:
            Content-Range:
              description: The actual range of the resource
              schema:
                type: string
          content:
            application/problem+json:
              schema:
                type: object
                properties:
                  type:
                    type: string
                    example: "https://example.com/problems/range-not-satisfiable"
                  title:
                    type: string
                    example: "Range Not Satisfiable"
                  status:
                    type: integer
                    example: 416
                  detail:
                    type: string
                    example: "The requested range cannot be satisfied"
                  instance:
                    type: string
                    example: "/largefile"
        '200':
          description: Successful response (if no Range header is used)
        '400':
          description: Bad Request (if the Range header is malformed)

避免重複定義已知標頭

根據 ADP-767,你應該(SHOULD)使用已經定義好的共用標頭檔案或至少使用 #/components/headers,以避免重新定義所有已知標頭。

語意

請參閱 ADP-351: 範圍請求

關聯 ADPs

References