Reject invalid ArrayConnection cursors - #5715
Conversation
| if index.nil? || index <= 0 | ||
| raise GraphQL::ExecutionError, "Invalid cursor: #{cursor.inspect}" | ||
| end | ||
| [index, items.length + 1].min |
There was a problem hiding this comment.
I want to make sure I understand this right:
If you have a (stale) cursor from previously fetching this Array, and the Array is now shorter than it used to be (so that your stale cursor is now out-of-bounds), will the code still return an empty result set, or will it raise an error?
(I think it will return an empty result set, which is the correct behavior per https://relay.dev/graphql/connections.htm#sec-Pagination-algorithm -- I just want to make sure I understand correctly!)
There was a problem hiding this comment.
Yes, that's correct. Positive out-of-bounds cursors are still accepted. The index is capped at items.length + 1, so an after cursor beyond the current Array slices past the end and returns an empty result set. Only malformed, zero, or negative cursors raise an error.
The existing “handles out-of-bounds cursors” test covers this with an encoded cursor value of "100", which is equivalent to a stale cursor from a previously longer Array. Thanks for checking!
387dbea to
940040c
Compare
|
Sounds good, thanks for this! |
GraphQL::Pagination::ArrayConnectioncurrently converts decoded cursors withString#to_iand uses the result directly as an Array index.This allows negative cursor offsets to wrap around to the end of the Array:
Malformed values are also partially or silently converted:
As a result, invalid client-provided cursors can return unrelated pages and produce incorrect pageInfo values.
This PR parses decoded ArrayConnection cursors with Integer and raises GraphQL::ExecutionError for malformed, zero, or negative values. Positive offsets beyond the Array continue to return an empty page, preserving the existing out-of-bounds behavior. Very large positive integers are capped to a safe sentinel index so they cannot raise a Ruby RangeError.