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

feat: link pagination with query parameters and improve wording (#445) #454

Merged
merged 8 commits into from
Oct 16, 2018

Conversation

tkrop
Copy link
Member

@tkrop tkrop commented Sep 25, 2018

Closes #445.

This change tries to better communicate a consistent look and feel of APIs.

While it replaces a MAY by a MUST, I think this was the intended semantic for providing conventional query parameters supporting query parameters for searching, sorting, filtering, and paginating. Thus I'm not sure whether this is a guideline change.

I also remove the alternate size for limit, and page for offset to enforce a stricter look and feel. If voted for I will reintroduce them again.

@tkrop tkrop self-assigned this Sep 25, 2018
@tkrop tkrop force-pushed the 445-link-pagination-with-standard-query-parameters branch from 0e8f342 to fcbc941 Compare September 25, 2018 09:12
"expand" correctly is difficult, so do it with care. See <<158>> below.
* `cursor` — key-based page start. See <<pagination>> section below.
* `offset` — numeric offset page start. See <<pagination>> section below.
Hint: In combination with limit, you can use page as an alternative to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

page with code ticks and doesn't page have a different semantic then offset?

My understanding:

  • offset is the absolute number of records
  • page is offset/limit
  • limit can be understood as a page size

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damned, I missed this. I wanted to remove this too.

@tkrop
Copy link
Member Author

tkrop commented Sep 25, 2018

@whiskeysierra thanks for the comment. Do you think we should keep page and size as an alternative?

@whiskeysierra
Copy link
Contributor

Do you think we should keep page and size as an alternative?

No, but we may add better descriptions to each parameter to make their semantic clear.

@tkrop
Copy link
Member Author

tkrop commented Sep 25, 2018

@whiskeysierra good idea.

should have an entity specific alias, like sku
* `sort` — comma-separated list of fields to define the sort order. To
indicate sorting direction, fields may be prefixed with + (ascending) or
- (descending, default), e.g. /sales-orders?sort=+id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is descending the default?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I realize that you didn't introduce that, just asking.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@whiskeysierra I also only guess, but I think order is often based on date. Thus descending might make sense to see the most resent results first. But I would like to question this as you. Lets remove this!

`embed` correctly is difficult, so do it with care. See <<158>> below.
* `offset` — numeric offset of the first element on a page. See <<pagination>>
section below.
* `cursor` — encoded pointer to the first or last element on a page, the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that an implementation detail? From an abstract perspective the cursor just addresses a single page, doesn't it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@whiskeysierra Yes, it is an implementation detail, that describes best practice. It is based on my experience in the workshops that many developers have no idea how to start. Thus, I think it might be helpful to have a description about what a cursor is about. When I start to explain this, I often see people starting to understand this concept. What do you think.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm skipping over my belief that we shouldn't document cursor at all and I might open up that discussion separately.

Let's try to split apart the API and implementation aspects more clearly then. Clients should only care about the contract that a cursor provides (opaque value, never to be inspected/constructed, addresses a single page) while providers care about implementation hints (cursor encodes direction although I'm still not a big fan of that, forward and backward cursors address the first/last item of the page respectively).

Mixing both in a sentence creates some confusion that we can try to avoid.

@tkrop tkrop force-pushed the 445-link-pagination-with-standard-query-parameters branch from 0fb5d38 to d0156ea Compare September 28, 2018 12:02
`embed` correctly is difficult, so do it with care. See <<158>> below.
* `offset` — numeric offset of the first element on a page. See <<pagination>>
section below.
paque value, never to be inspected/constructed, addresses a single page
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opaque

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, intended to remove this fragment. Not supposed to be part of offset definition.

* `embed` — to expand or embedded sub-entities (ie.: inside of an article
entity, expand silhouette code into the silhouette object). Implementing
`embed` correctly is difficult, so do it with care. See <<158>> below.
* `offset` — numeric offset of the first element on a page. See <<pagination>>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we define offset and cursor independently? Wouldn't it be beneficial for both to be indistinguishable to clients so that servers can migrate from one to the other?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of offset, there may be a use case for setting the value manually. Unless we propose a more advanced scheme for pagination links with, the offset is not opaque.

paque value, never to be inspected/constructed, addresses a single page
* `cursor` — an opaque pointer to a page, never to be inspected/constructed by
clients. It usually (encrypted) encodes the identifier of the first or last
page element, the pagination direction, and the applied query filters to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't encrypt the query filters in the cursor. Those are query parameters that clients should in fact modify (at least on the very first request when they start their pagination).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior of the pagination gets absolutely unpredictable, if you allow to change the query filters, e.g. the selector page element might even not belong to the page making the cursor fail. If you want to change the query filters, you have to paginate from begin. Thus, it is best practice to include the filters into the cursor, and neglect all query filters given in addition.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to change the query filters, you have to paginate from begin.

Agreed, but that requirement in itself doesn't dictate that all other query parameters need to be encoded/encrypted inside the cursor. It just needs to be part of the contract that clients are not allowed/meant to modify the pagination links in any which way.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can only check correctness of filters with the cursor, if you put them into the cursor. There is no other state information in pagination.

@ghost
Copy link

ghost commented Oct 4, 2018

👍

@tkrop
Copy link
Member Author

tkrop commented Oct 10, 2018

👍


* `q` — default query parameter (e.g. used by browser tab completion); should
have an entity specific alias, like sku
* `sort` — comma-separated list of fields to define the sort order. To indicate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it have to be comma-separated? We specify the format for collection query parameters in 154. A link to the rule would be nice.

@maxim-tschumak
Copy link
Contributor

👍

@tkrop tkrop merged commit 1c6761f into master Oct 16, 2018
@tkrop tkrop deleted the 445-link-pagination-with-standard-query-parameters branch October 16, 2018 13:31
@maxim-tschumak maxim-tschumak mentioned this pull request Oct 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants