|
| 1 | +### Pagination |
| 2 | + |
| 3 | +Containers MAY hold a large number of resources. To allow clients to retrieve container listings incrementally, servers MUST support pagination for containers whose membership exceeds a server-determined threshold. |
| 4 | + |
| 5 | +#### Pagination Model |
| 6 | + |
| 7 | +Pagination is link-based: the server provides pagination URIs via HTTP `Link` headers [[!RFC8288]], allowing clients to navigate the full listing without relying on numeric offsets. The server determines page boundaries and page size. |
| 8 | + |
| 9 | +When a container listing is paginated, the response body contains only the current page of items. The container's `id`, `type`, and `totalItems` properties reflect the full container, while `items` contains only the resources on the current page. |
| 10 | + |
| 11 | +#### Pagination Link Relations |
| 12 | + |
| 13 | +Pagination URIs are conveyed in `Link` headers using the following standard link relations: |
| 14 | + |
| 15 | +- **`rel="first"`**: The URI of the first page of results. MUST be present on paginated responses. |
| 16 | +- **`rel="last"`**: The URI of the last page of results. MUST be present on paginated responses. |
| 17 | +- **`rel="next"`**: The URI of the next page of results. MUST be present when there are subsequent pages. MUST be omitted on the last page. |
| 18 | +- **`rel="prev"`**: The URI of the previous page of results. MUST be present when there are preceding pages. MUST be omitted on the first page. |
| 19 | + |
| 20 | +All pagination URIs are opaque to the client. Clients MUST NOT construct or modify pagination URIs; they MUST use the URIs provided by the server. |
| 21 | + |
| 22 | +#### Requesting Pages |
| 23 | + |
| 24 | +A client requests the container URI to obtain the first page. The response includes pagination Link headers that the client follows to retrieve subsequent pages. Servers MAY also support direct access to specific pages via the pagination URIs. |
| 25 | + |
| 26 | +When a paginated response is returned, the server MUST respond with 200 OK. The `totalItems` property in the response body MUST reflect the total number of items across all pages, not just the current page. |
| 27 | + |
| 28 | +#### Example: Paginated Container |
| 29 | + |
| 30 | +Request: |
| 31 | +``` |
| 32 | +GET /alice/photos/ HTTP/1.1 |
| 33 | +Authorization: Bearer <token> |
| 34 | +Accept: application/lws+json |
| 35 | +``` |
| 36 | + |
| 37 | +Response (first page): |
| 38 | +``` |
| 39 | +HTTP/1.1 200 OK |
| 40 | +Content-Type: application/lws+json |
| 41 | +ETag: "photos-page1-etag" |
| 42 | +Link: </alice/photos/.meta>; rel="linkset"; type="application/linkset+json" |
| 43 | +Link: </alice/>; rel="up" |
| 44 | +Link: </alice/photos/.acl>; rel="acl" |
| 45 | +Link: <https://www.w3.org/ns/lws#Container>; rel="type" |
| 46 | +Link: </alice/photos/?page=1>; rel="first" |
| 47 | +Link: </alice/photos/?page=3>; rel="last" |
| 48 | +Link: </alice/photos/?page=2>; rel="next" |
| 49 | +
|
| 50 | +{ |
| 51 | + "@context": "https://www.w3.org/ns/lws/v1", |
| 52 | + "id": "/alice/photos/", |
| 53 | + "type": "Container", |
| 54 | + "totalItems": 150, |
| 55 | + "items": [ |
| 56 | + { |
| 57 | + "type": "DataResource", |
| 58 | + "id": "/alice/photos/vacation.jpg", |
| 59 | + "mediaType": "image/jpeg", |
| 60 | + "size": 248392, |
| 61 | + "modified": "2025-11-20T10:30:00Z" |
| 62 | + }, |
| 63 | + { |
| 64 | + "type": "DataResource", |
| 65 | + "id": "/alice/photos/portrait.png", |
| 66 | + "mediaType": "image/png", |
| 67 | + "size": 102400, |
| 68 | + "modified": "2025-11-21T14:15:00Z" |
| 69 | + } |
| 70 | + ] |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +Request (next page): |
| 75 | +``` |
| 76 | +GET /alice/photos/?page=2 HTTP/1.1 |
| 77 | +Authorization: Bearer <token> |
| 78 | +Accept: application/lws+json |
| 79 | +``` |
| 80 | + |
| 81 | +Response (middle page): |
| 82 | +``` |
| 83 | +HTTP/1.1 200 OK |
| 84 | +Content-Type: application/lws+json |
| 85 | +ETag: "photos-page2-etag" |
| 86 | +Link: </alice/photos/.meta>; rel="linkset"; type="application/linkset+json" |
| 87 | +Link: </alice/>; rel="up" |
| 88 | +Link: </alice/photos/.acl>; rel="acl" |
| 89 | +Link: <https://www.w3.org/ns/lws#Container>; rel="type" |
| 90 | +Link: </alice/photos/?page=1>; rel="first" |
| 91 | +Link: </alice/photos/?page=1>; rel="prev" |
| 92 | +Link: </alice/photos/?page=3>; rel="next" |
| 93 | +Link: </alice/photos/?page=3>; rel="last" |
| 94 | +
|
| 95 | +{ |
| 96 | + "@context": "https://www.w3.org/ns/lws/v1", |
| 97 | + "id": "/alice/photos/", |
| 98 | + "type": "Container", |
| 99 | + "totalItems": 150, |
| 100 | + "items": [ |
| 101 | + { |
| 102 | + "type": "DataResource", |
| 103 | + "id": "/alice/photos/sunset.jpg", |
| 104 | + "mediaType": "image/jpeg", |
| 105 | + "size": 315000, |
| 106 | + "modified": "2025-11-22T09:00:00Z" |
| 107 | + } |
| 108 | + ] |
| 109 | +} |
| 110 | +``` |
0 commit comments