Skip to content

/query does not forward RERUM's Pagination-* response headers #131

Closed

Description

@thehabes

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 /query response carries every Pagination-* header RERUM returned
  • A 502 from /query carries every Pagination-* 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

  1. changed the title [-]`/query` drops RERUM's pagination headers and reports RERUM's `limit`/`skip` rejections as 502[/-] [+]`/query` does not forward RERUM's `Pagination-*` response headers[/+] on Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions