Open
Conversation
7f9c148 to
31e727b
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
31e727b to
1606fe2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pagination in headers: Range request header and content-range response handling.
I created a PR for this topic, please see the issue for the 'why it's cool'.
For now, there is 2 separate commits:
Range request header
This commit adds server-side parsing of the Range request header, enabling clients to request specific slices of a collection via standard HTTP semantics.
RFC 9110 sections followed
§14.2 Range — defines the request header format:
Range: <unit>=<first-pos>-<last-pos>. Unrecognized formats or units are silently ignored (the server delegates normally), as recommended by the spec.§15.3.7 206 Partial Content — the response status when a valid Range request is successfully fulfilled. The operation status is set to
206soRespondProcessorreturns it alongside theContent-Rangeheader.§15.5.17 416 Range Not Satisfiable — returned when the range is syntactically valid but not satisfiable (start > end, or range not aligned to page boundaries).
Summed up design considerations
Main logic implemented
RangeHeaderProviderdecorator on the read provider — parses theRangeheader, converts the range to page/itemsPerPage pagination filters via_api_filters, and sets the operation status to206. Follows the same decorator pattern asJsonApiProvider.provider.php— decoratesapi_platform.state_provider.read(at priority 1).Tests
RangeHeaderProviderTest— 9 unit tests covering delegation (no header, wrong operation type, wrong HTTP method), ignored formats (unparseable, wrong unit), valid ranges, and416errors.ContentRangeHeaderTest— verify the full flow: Range header in →206status +Content-Rangeheader out.Content-range response header
This commit adds RFC 9110-compliant Content-Range and Accept-Ranges response headers to all paginated collection endpoints.
RFC 9110 sections followed
§14.4 Content-Range — defines the header grammar:
range-unit SP (range-resp/unsatisfied-range). We use custom range units (for examplebook) as allowed by the extensible range unit mechanism. The unsatisfied-range production (*/complete-length) requirescomplete-lengthto be a digit, so the header is omitted when both the page is empty and the total is unknown (since*/*would be invalid ABNF).§14.3 Accept-Ranges — advertises which range unit the server supports for a given resource. Sent on every paginated collection response.
§14.1 Range Units — confirms that range units are extensible tokens, not limited to
bytes.§15.3.7 206 Partial Content — clarifies that
206is strictly reserved for responses toRangerequests. Since this commit only handles the response side (noRangerequest parsing yet), the status code remains200.Summed up design considerations
Main logic implemented
HttpResponseHeadersTrait::addContentRangeHeaders()— fetches range from paginator (0-indexed offsets) and emits theContent-Range&Accept-Rangesheaders.Tests
ContentRangeHeaderTest— 11 test cases covering partial collections, full collections, page offsets, unknown totals, empty pages, non-collection operations, and the unit fallback.Limitations & concerns
HEADverb, to just receive pagination through header'sContent-range, doesn't save any cycles as it is processed just like aGET. The content is stripped right before sending the response. There's a clear room for improvement here! → Will be in a totally separated issue, because it's another topic.200responses but API-Platform fires some206),ContentRangeHeaderTest&RangeHeaderProviderTestto help designing the feature. We can totally merge everything in other testfiles if wanted.feat(state): ...→ is it really the best domain? Don't we have a headers domain?Content-Range&Rangetopics can totally be in 2 separate PR, if you want to zoom in for reviews & discussions. Let me know.Content-Range. I put it in plural because it was easy in current implementation.