hypothesis / h

Annotate with anyone, anywhere.
https://hypothes.is/
BSD 2-Clause "Simplified" License
2.96k stars 427 forks source link

Add explicit link to next page of results in search API #7841

Open robertknight opened 1 year ago

robertknight commented 1 year ago

The search API supports cursor-based pagination using the search_after parameter. The responses do not include an explicit link to the next page of results, so API clients have to figure out how to construct that themselves, and also how to tell when they have reached the end of the results. This has caused some problems:

What I would suggest we do is add an explicit "next page" link to the results, which is omitted for the last page. Some examples in other APIs:

Of the approaches above, I think I would favor a field in the JSON response, as being easier to discover and to parse.

acelaya commented 1 year ago

+1 to the _links approach. I agree it's easier to discover. Anyone debugging the API will quickly find about it, as the response body is what one usually inspects first when messing around with an API.

I've also seen that more often.

robertknight commented 1 year ago

The Confluence API is similar to https://stateless.co/hal_specification.html (see also https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-08), but slightly different, as link values are just strings, as opposed to objects in the HAL spec.

robertknight commented 1 year ago

Some more resources:

Blog post about different ways of embedding links in APIs: https://evertpot.com/json-links/ JSON API profile for cursor pagination: https://jsonapi.org/profiles/ethanresnick/cursor-pagination/#profile-intro.

kael commented 1 year ago

Some examples in other APIs:

There's also a possible use of the HTTP Range header field - although not sure it completely fits the requirements.

From Range header, I choose you (for pagination)! :

200 OK Accept-Ranges: users Content-Range: users 0-9/200

[ 0, …, 9 ]


- Requesting past the end of the collection :
```http
GET /users
Range: users=1000-

416 Requested Range Not Satisfiable

206 Partial Content Accept-Ranges: users Content-Range: users 195-199/200

[ 195, …, 199 ]



Pity there's no standard JS API for parsing `<Link/>` headers.
kael commented 1 year ago

There's also a possible use of the HTTP Range header field - although not sure it completely fits the requirements.

It does not fit the requirements, indeed. I was a bit too happy to get all informations using a HEAD request, but it's not easily parsable out-of-the box

(I'm querying the API to get the total count of annotations per URI using limit=0, I was thinking that a HEAD could replace it).

kael commented 1 year ago

What I would suggest we do is add an explicit "next page" link to the results, which is omitted for the last page.

It'd be interesting to include the first and last annotations of the whole result.

With pagination, to be able to display next and previous buttons, for a query I'm also fetching the first (order=asc&limit=1) and last (order=desc&limit=1) annotations so that if the first annotation of the whole result is equal to the first annotation of the annotations slice the next <button/> is disabled.