Skip to content

Commit ebac8fb

Browse files
laurensdebTallTedpchampin
authored
feat: pagination for LWS Containers (#82)
* feat: add pagination support for container listings Add link-based pagination model for large containers with first/last/ next/prev navigation URIs. Add pagination section to spec, extend container representation with pagination properties, and add pagination terms to JSON-LD context. * chore: formatting Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com> * Apply suggestions from code review Co-authored-by: Pierre-Antoine Champin <pierre-antoine@w3.org> * chore: implement feedback * fix: minor restructuring * fix: clarify pagination model description Removed redundant sentence about server determining page boundaries and size. --------- Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com> Co-authored-by: Pierre-Antoine Champin <pierre-antoine@w3.org>
1 parent 7d2056f commit ebac8fb

2 files changed

Lines changed: 129 additions & 2 deletions

File tree

lws10-core/container-representation.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ A container representation MUST include the following properties:
88

99
- **`id`**: The URI of the container.
1010
- **`type`**: The value `"Container"`.
11-
- **`totalItems`**: An integer indicating the total number of resources contained in the container which can be disclosed to the client.
12-
- **`items`**: An array of contained resource descriptions (see below). If the container is empty, this MUST be an empty array.
11+
- **`totalItems`**: An integer indicating the total number of resources
12+
contained in the container which can be disclosed to the client.
13+
- **`items`**: An array of contained resource descriptions (see below). If the
14+
container is empty, this MUST be an empty array. When the container listing is
15+
paginated, `items` contains only the current page of resources; see [Pagination](#pagination) for details.
1316

1417
#### Contained Resource Description
1518

lws10-core/lws-media-type.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,127 @@ Servers MUST support content negotiation for container representations. The resp
1313
- If a client requests `application/json`, the server MUST respond with `Content-Type: application/json`.
1414

1515
In all three cases, the response body is the same JSON-LD document conforming to the LWS container vocabulary. Servers are free to support additional media types (e.g., `text/turtle`) through content negotiation.
16+
17+
18+
#### Pagination
19+
20+
Certain composite resources, like containers, may hold a large number of resources.
21+
To allow clients to retrieve listings incrementally, servers SHOULD support
22+
pagination for containers whose membership exceeds a server-determined threshold.
23+
24+
##### Pagination Model
25+
26+
Pagination is link-based: the server provides pagination URIs via HTTP `Link` headers [[!RFC8288]],
27+
allowing clients to navigate the full listing without relying on numeric offsets.
28+
29+
When a listing is paginated, the response body contains only the current page of items. The
30+
composite resource's `id`, `type`, and `totalItems` properties reflect the full membership, while `items`
31+
contains only the resources on the current page.
32+
33+
##### Pagination Link Relations
34+
35+
Pagination URIs are conveyed in `Link` headers using the following standard link relations:
36+
37+
- **`rel="first"`**: The URI of the first page of results. MUST be present on paginated responses.
38+
- **`rel="last"`**: The URI of the last page of results. MAY be present on paginated responses.
39+
- **`rel="next"`**: The URI of the next page of results. MUST be present when there are subsequent
40+
pages. MUST be omitted on the last page.
41+
- **`rel="prev"`**: The URI of the previous page of results. MAY be present when there are preceding
42+
pages. MUST be omitted on the first page.
43+
44+
All pagination URIs are opaque to the client. Clients SHOULD NOT construct or modify pagination
45+
URIs; they SHOULD use the URIs provided by the server.
46+
47+
##### Requesting Pages
48+
49+
A client requests the composite resource's URI to obtain the first page. The response includes pagination
50+
Link headers that the client follows to retrieve subsequent pages. Servers MAY also support
51+
direct access to specific pages via the pagination URIs obtained during a previous scan.
52+
53+
When a paginated response is returned, the server MUST respond with 200 OK. The `totalItems`
54+
property in the response body MUST reflect the total number of items across all pages, not just the
55+
current page.
56+
57+
##### Example: Paginated Container
58+
59+
Request:
60+
```
61+
GET /alice/photos/ HTTP/1.1
62+
Authorization: Bearer <token>
63+
Accept: application/lws+json
64+
```
65+
66+
Response (first page):
67+
```
68+
HTTP/1.1 200 OK
69+
Content-Type: application/lws+json
70+
ETag: "photos-page1-etag"
71+
Link: </alice/photos/.meta>; rel="linkset"; type="application/linkset+json"
72+
Link: </alice/>; rel="up"
73+
Link: </alice/photos/.acl>; rel="acl"
74+
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
75+
Link: </alice/photos/?page=1>; rel="first"
76+
Link: </alice/photos/?page=3>; rel="last"
77+
Link: </alice/photos/?page=2>; rel="next"
78+
79+
{
80+
"@context": "https://www.w3.org/ns/lws/v1",
81+
"id": "/alice/photos/",
82+
"type": "Container",
83+
"totalItems": 150,
84+
"items": [
85+
{
86+
"type": "DataResource",
87+
"id": "/alice/photos/vacation.jpg",
88+
"mediaType": "image/jpeg",
89+
"size": 248392,
90+
"modified": "2025-11-20T10:30:00Z"
91+
},
92+
{
93+
"type": "DataResource",
94+
"id": "/alice/photos/portrait.png",
95+
"mediaType": "image/png",
96+
"size": 102400,
97+
"modified": "2025-11-21T14:15:00Z"
98+
}
99+
]
100+
}
101+
```
102+
103+
Request (next page):
104+
```
105+
GET /alice/photos/?page=2 HTTP/1.1
106+
Authorization: Bearer <token>
107+
Accept: application/lws+json
108+
```
109+
110+
Response (middle page):
111+
```
112+
HTTP/1.1 200 OK
113+
Content-Type: application/lws+json
114+
ETag: "photos-page2-etag"
115+
Link: </alice/photos/.meta>; rel="linkset"; type="application/linkset+json"
116+
Link: </alice/>; rel="up"
117+
Link: </alice/photos/.acl>; rel="acl"
118+
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
119+
Link: </alice/photos/?page=1>; rel="first"
120+
Link: </alice/photos/?page=1>; rel="prev"
121+
Link: </alice/photos/?page=3>; rel="next"
122+
Link: </alice/photos/?page=3>; rel="last"
123+
124+
{
125+
"@context": "https://www.w3.org/ns/lws/v1",
126+
"id": "/alice/photos/",
127+
"type": "Container",
128+
"totalItems": 150,
129+
"items": [
130+
{
131+
"type": "DataResource",
132+
"id": "/alice/photos/sunset.jpg",
133+
"mediaType": "image/jpeg",
134+
"size": 315000,
135+
"modified": "2025-11-22T09:00:00Z"
136+
}
137+
]
138+
}
139+
```

0 commit comments

Comments
 (0)