fix: skip URL rewriting for non-relation field values - #183
Merged
Conversation
A "?fields=" query selecting scalar fields returned corrupted values:
plain strings were percent-encoded ("Book 1" -> "Book%201") and numbers
were coerced to strings (2019 -> "2019"). The header form was unaffected
because it never rewrites the response body.
The relation handler ran for every scalar leaf, including pure field
projections that are not relations. Those values were parsed with
url.Parse and re-serialized via url.URL.String(), which percent-encodes
the path and stringifies numbers.
Guard the handler so a node with no relation to push and no child
selector to propagate is left untouched. Besides fixing the corruption,
this skips url.Parse, the query re-encoding and the json.Marshal for
every projected scalar, cutting allocations on the fields path by ~30%.
Fixes #96
dunglas
approved these changes
Jul 25, 2026
Owner
|
Good catch! Thanks. |
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.
Problem
Fixes #96.
A
?fields=query that selects scalar fields returns corrupted values:"Book 1"→"Book%201","Roland Garros 2019"→"Roland%20Garros%202019";2019→"2019"(a float is even truncated).The bug only affects the query form (
?fields=), not the header form (Fields:), which is why it surfaced with parametrized queries.Root cause
In
Apply, the relation handler is invoked for every scalar leaf of the document — including pure field projections that are not relations. Each such value is parsed withurl.Parseand re-serialized withurl.URL.String(), which percent-encodes the path; numbers are additionally re-marshalled from a string. Only the query form rewrites the body (urlRewriter+u.String()), so only it exposes the corruption.Fix
Guard the handler so a node that is not a relation — no relation to push (
preload) and no child selector to propagate — is returned untouched, before any URL machinery runs:The query-vs-header propagation logic is left intact; the guard only restores the precondition that block always assumed — that it operates on relations.
Efficiency
Because the guard short-circuits before
url.Parse, the query re-encoding and thejson.Marshal, it also removes wasted work on the fields path. Benchmark on a?fields=query selecting 7 scalar fields (5 runs, Go 1.26):Benchmark used
Tests
Two regression tests added in
server_test.go(a numericyearfield was added to the JSON-LD fixture to cover type preservation):TestFieldsQueryDoesNotEncodePlainValues—"Book 1"stays"Book 1";TestFieldsQueryPreservesNumberType—2019stays a JSON number.