[ADP-137] Range
Overview
The Range header in HTTP allows clients to request specific portions of a resource, rather than the entire resource. This can be useful for efficiently handling large data sets, providing partial responses, and supporting resumable downloads. While primarily used for byte ranges, it can also be adapted for other units in RESTful APIs, such as items or records. However, careful documentation and adherence to standards are necessary to ensure correct implementation and client-server interaction.
Guidance
The Range header SHOULD NOT be used for pagination. Refer to ADP-312: Pagination for preferred practices.
If pagination based on Range must be used, clearly specify the units being used.
Example of Range-based pagination:
```http GET /users Range: users=0-9 206 Partial Content Accept-Ranges: users Content-Range: users 0-9/200 ```
In the example above, the unit is
users
. It should be the plural form of the resource/entity type.
For more complex use cases, the Range header MAY specify byte ranges, as detailed in RFC 9110.
Example of byte range values:
``` bytes=-500 bytes=9500- bytes=0-0,-1 bytes=0-999,4500-5499,-1000 ```
The server SHOULD respond with HTTP status 416 (Range Not Satisfiable) if the requested Range cannot be fulfilled or the specified unit is not supported.
Use HTTP Problem Details (RFC 9457) to provide more information about the error.
```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": "The requested range cannot be satisfied", "instance": "/images/{image-id}" } ```
Example
Consider an API endpoint for retrieving parts of a large file. Here’s how you might implement Range headers for partial content retrieval
GET /largefile HTTP/1.1
Range: bytes=0-999
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 0-999/5000
If the client requests a range that cannot be satisfied:
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": "The requested range cannot be satisfied",
"instance": "/largefile"
}
OpenAPI Example
To document the use of the Range header in OpenAPI specifications, you can use the following example:
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)
Refrain from redefining known headers
As per ADP-767, you SHOULD utilize the external headers definition YAML or reference #/components/headers
using $refs
, thereby avoiding the redefinition of known headers across all operations.
Semantics
Refer to ADP-351: Range Requests.