Repository navigation
/query does not forward RERUM's Pagination-* response headers #131
Description
Summary
RERUM API PR rerum_server_nodejs#310, deployed on devstore now, reports pagination on /query responses with four headers:
Pagination-Limit: 500
Pagination-Skip: 0
Pagination-Limit-Max: 500
Pagination-Skip-Max: 100000
The applied values come back on every paged 200.
The two maximums also come back on a limit/skip rejection, such as a skip past the maximum.
TinyNode's routes/query.js does not forward them.
It reads only the body from RERUM (routes/query.js#L37-L49) and builds a fresh response, so the headers are dropped on both the success and the error path.
Why this matters
A TinyNode client cannot tell a truncated page from a final one.
?limit=1000 is clamped to 500 by RERUM, and devstore says so in Pagination-Limit: 500.
tinydev returns the same 500 records with nothing on the wire to say they were clamped.
On an error, a client that hits the skip ceiling cannot read Pagination-Skip-Max to learn where the ceiling is.
The 502 status is fine; the headers just need to come along with it.
Evidence
Verified 2026-09-14, read-only, body {"type":"Annotation"}.
| Request | devstore directly | tinydev |
|---|---|---|
?limit=1000 |
200 with all four Pagination-* headers |
200, no Pagination-* headers |
?skip=100001 |
400 with Pagination-Limit-Max and Pagination-Skip-Max |
502, no Pagination-* headers |
tinydev already sends Access-Control-Expose-Headers: *, so browser clients can read the headers once they are forwarded.
Proposed change
Copy any Pagination-* headers RERUM returned onto TinyNode's response, before branching on resp.ok, so they survive both the 200 and the 502.
const PAGINATION_HEADERS = ["Pagination-Limit", "Pagination-Skip", "Pagination-Limit-Max", "Pagination-Skip-Max"]
const rerumResponse = await fetchRerum(queryURL, queryOptions)
.then(async (resp) => {
for (const header of PAGINATION_HEADERS) {
const value = resp.headers.get(header)
if (value !== null) res.set(header, value)
}
if (resp.ok) return resp.json()
// ...existing error handling, unchanged
})Headers set on res before the throw are kept when the route's catch sends the 502.
When RERUM sends none, for example store.rerum.io before #310 is released, nothing is forwarded.
The fetch mocks in test/routes/query.test.js return objects with no headers, so they need headers: new Headers() once the route reads them.
Acceptance criteria
- A successful
/queryresponse carries everyPagination-*header RERUM returned - A
502from/querycarries everyPagination-*header RERUM returned on its error response - No
Pagination-*headers are added when RERUM does not send them - Tests cover forwarding on both the success and error paths
Activity
[-]`/query` drops RERUM's pagination headers and reports RERUM's `limit`/`skip` rejections as 502[/-][+]`/query` does not forward RERUM's `Pagination-*` response headers[/+]