Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Listing with pagination #153

Merged
merged 3 commits into from
Apr 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions directory.td.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,59 @@
},
"retrieveTDs": {
"description": "Retrieve all Thing Descriptions",
"uriVariables": {
"offset": {
"title": "Number of TDs to skip before the page",
"type": "number",
"default": 0
},
"limit": {
"title": "Number of TDs in a page",
"type": "number"
},
"sort_by": {
"title": "Comparator TD attribute for collection sorting",
"type": "string",
"default": "id"
},
"sort_order": {
"title": "Sorting order",
"type": "string",
"enum": ["asc", "desc"],
"default": "asc"
}
},
"forms": [
{
"href": "/td",
"htv:methodName": "GET",
"response": {
"description": "Success response",
"htv:statusCodeValue": 200,
"contentType": "application/ld+json"
},
"scopes": "readAll"
},
{
"href": "/td{?offset,limit,sort_by,sort_order}",
"htv:methodName": "GET",
"response": {
"description": "Success response",
"htv:statusCodeValue": 200,
"contentType": "application/ld+json",
"htv:headers": [
{
"htv:fieldName": "Link"
}
]
},
"additionalResponses": [
{
"description": "Invalid query arguments",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
],
"scopes": "readAll"
}
]
Expand Down
124 changes: 122 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -964,8 +964,8 @@ <h4>Deletion</h4>
<h4>Listing</h4>
<p>
The listing endpoint provides a way to query the collection of TD objects
from the directory. The Search API may be used to retrieve <a>Partial TD</a>s
or TD fragments; see [[[#exploration-directory-api-search]]].
from the directory. The Search API may be used to retrieve TD fragments;
see [[[#exploration-directory-api-search]]].
</p>


Expand Down Expand Up @@ -1002,6 +1002,126 @@ <h4>Listing</h4>
</span>
</p>

<p>
There may be scenarios in which clients need to retrieve the collection
in small subsets of TDs.
While the Search API ([[[#exploration-directory-api-search]]])
does offer the ability to query a specific range, it may not be optimal,
nor developer-friendly.

<span class="rfc2119-assertion" id="tdd-reg-list-pagination">
The server MAY support pagination to return the collection
in small subsets.
</span>
The pagination must be based on the following rules:
<ul>
<li>
<span class="rfc2119-assertion" id="tdd-reg-list-pagination-limit">
When the `limit` query parameter is set to a positive integer,
the server MAY respond with a subset of TDs totalling
to less than or equal to the requested number.
</span>
</li>
<li>
<span class="rfc2119-assertion" id="tdd-reg-list-pagination-header-nextlink">
When there are more TDs after a returned subset of the collection,
the response MUST contain a `next` Link header [[RFC8288]]
with the URL of the next subset.
</span>
<span class="rfc2119-assertion" id="tdd-reg-list-pagination-header-nextlink-attr">
The `next` link MUST have the same `limit` argument given on the initial
request as well as a zero-based `offset` argument anchored at
the beginning of the next subset.
</span>
The link may be absolute or relative to directory API's base URL.
Moreover, it may include additional arguments that are necessary for
ordering or session management.
</li>
<li>
<span class="rfc2119-assertion" id="tdd-reg-list-pagination-header-canonicallink">
All paged responses MUST contain a `canonical` Link header
pointing to the collection and include an `etag` parameter to represent
the current state of the collection.
</span>
The link may be absolute or relative to directory API's base URL.
The `etag` value could be a revision number, timestamp, or UUID Version 4,
set whenever the TD collection changes in a way that affects the
ordering of the TDs.
The clients may rely on the `etag` value to know whether the collection
remains consistent across paginated retrieval of the collection.
For example, creation or deletion of TDs or update of TD fields used for
ordering may make shift the calculated paging window.
</li>
<li>
<span class="rfc2119-assertion" id="tdd-reg-list-pagination-order-default">
By default, the collection MUST be sorted alphanumerically
by the unique identifier of TDs.
</span>
<span class="rfc2119-assertion" id="tdd-reg-list-pagination-order">
The server MAY support sorting by other TD attributes using
query arguments: `sort_by` to select a field (e.g. `created`)
and `sort_order` to choose the order
(i.e. `asc` or `desc` for ascending and descending ordering).
</span>
<span class="rfc2119-assertion" id="tdd-reg-list-pagination-order-unsupported">
If the server does not support custom sorting,
it MUST reject the request with 501 (Not Implemented) status.
</span>
<span class="rfc2119-assertion" id="tdd-reg-list-pagination-order-nextlink">
If sorting attributes are accepted, they MUST be added consistently to all `next` links.
</span>
</li>
</ul>

The following example provides a walk-through of the paginated
retrieval of TDs:

<aside class="example" id="example-pagination"
title="Query 12 TDs with page size 10.">
The client requests the list with a `limit` of 10:
<pre>
GET /td?limit=10 HTTP/1.1
Host: tdd.example.com
</pre>
Response:
<pre>
HTTP/1.1 200 OK
Content-Type: application/ld+json
Link: &#x3C;/td?offset=10&#x26;limit=10&#x3E;; rel=&#x22;next&#x22;
Link: &#x3C;/td&#x3E;; rel=&#x22;canonical&#x22;; etag=&#x22;v1&#x22;

[{ TD }, ...9 other TDs... ]
</pre>
The response includes two Link headers with relative URLs:
`next` link to query the remaining TDs,
`canonical` link referencing the full collection with `etag` value indicating
the state of that collection.
<br>
The response body is an array of 10 TDs.

<br><br>
The presence of the `next` link implies that subsequent pages should be
queried for the remaining TDs.
The client requests the next page via the `next` link:
<pre>
GET /td?offset=10&limit=10 HTTP/1.1
Host: tdd.example.com
</pre>

Response:
<pre>
HTTP/1.1 200 OK
Content-Type: application/ld+json
Link: &#x3C;/td&#x3E;; rel=&#x22;canonical&#x22;; etag=&#x22;v1&#x22;

[{ TD }, { TD }]
</pre>
The server response has the remaining two TDs. There is no `next` link,
because this is the last page. The `etag` value has not changed implying
that the collection has remained consistent between the two requests.
</aside>
</p>

<p>
The paginated list operation is specified as `retrieveTDs` property in
[[[#directory-thing-description]]].
Expand Down