Skip to content

fix(http): bind every occurrence of a repeated query parameter - #4

Merged
juicycleff merged 2 commits into
mainfrom
fix/bind-repeated-query-params
Aug 25, 2026
Merged

fix(http): bind every occurrence of a repeated query parameter#4
juicycleff merged 2 commits into
mainfrom
fix/bind-repeated-query-params

Conversation

@juicycleff

Copy link
Copy Markdown
Contributor

bindFormParam learned to fill a []string from a repeated parameter in
v1.1.7. bindQueryParam did not, and still reads one value through Query, so
a []string query field takes the first occurrence and drops the rest.

Why this is worse than the bug it replaced

Before setFieldValue grew a slice case, that same field failed the request
outright with "unsupported field type". Loud, and impossible to miss.

Now the lone value it does read gets split on commas instead, so the request
succeeds carrying less than the caller sent. For an RFC 8707 resource
indicator that means an access token scoped to fewer audiences than were asked
for, with nothing logged and nothing returned to say so. Silent narrowing of an
authorization boundary is the failure mode you least want.

Measured before the change:

binding path resource=a&resource=b
bindFormParam ["a", "b"]
bindQueryParam ["a"]

What changed

The query path now mirrors the form path, the same branch in the same order:

  • a repeated parameter is taken verbatim
  • a lone value still expands on commas, the way scope=openid,profile always has
  • an absent parameter still falls back to the default tag
  • a required one still reports itself missing

Reusing isMultiValueTarget and setSliceFieldValue means the two paths cannot
drift apart on what counts as a slice target or how elements get converted.

Seven tests cover those cases, including the one that pins the asymmetry: a
lone scope=openid,email splits, while a repeated scope=openid&scope=a,b
keeps a,b whole. Both failed before the change for the repeated cases and
passed for the rest, so the existing behaviour is nailed down as well as the
new.

Not included

Header parameters have the same shape and the same gap. Repeated headers are
rarer and nothing is waiting on them, so bindHeaderParam is untouched here
rather than changed without a caller to justify it.

Downstream

authsome's OAuth2 authorization endpoint reads resource off the raw request
today, purely to work around this. Once this ships it becomes an ordinary
[]string field with a query tag, which also puts the parameter in the
generated OpenAPI document for the first time, and therefore in the generated
clients.

bindFormParam learned to fill a []string from a repeated parameter, but
bindQueryParam kept reading one value through Query. A []string query
field therefore took the first occurrence and dropped the rest.

That is quieter than it used to be, and worse. Before setFieldValue
grew a slice case the same field failed the request outright with
"unsupported field type". Now the lone value it does read gets split on
commas instead, so the request succeeds carrying less than the caller
sent. For an RFC 8707 resource indicator that means an access token
scoped to fewer audiences than were asked for, with nothing logged.

The query path now mirrors the form path exactly: a repeated parameter
is taken verbatim, a lone value still expands on commas the way
scope=openid,profile always has, an absent parameter falls back to the
default tag, and a required one still reports itself missing.

Header parameters have the same shape and are left alone here. Repeated
headers are rarer and nothing is waiting on them.
@juicycleff
juicycleff merged commit 6b31905 into main Aug 25, 2026
13 checks passed
@juicycleff
juicycleff deleted the fix/bind-repeated-query-params branch August 25, 2026 20:26
github-actions Bot added a commit that referenced this pull request Aug 25, 2026
## [1.1.8](v1.1.7...v1.1.8) (2026-08-25)

### Bug Fixes

* **http:** bind every occurrence of a repeated query parameter ([#4](#4)) ([6b31905](6b31905))
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.1.8 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

juicycleff added a commit to xraph/authsome that referenced this pull request Aug 25, 2026
xraph/go-utils#4 shipped as v1.1.8. bindQueryParam now fills a []string from
every occurrence of a repeated query parameter, the way bindFormParam already
did, and a lone value still expands on commas so scope=openid,profile is
unaffected.

That is the release the previous commit said it was waiting for. The three
tests it listed as failing against v1.1.7 pass now, and they fail for the right
reason without this bump: two_resources_both_land_on_the_code kept only the
first resource, and the two TestTokenResource cases were downstream of the same
collapse.

Nothing else moves. The spec and all three SDKs regenerate byte-identical, the
full suite passes and the linter is quiet, because the code this unblocks was
already written and only the dependency was missing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant