-
-
Notifications
You must be signed in to change notification settings - Fork 46
Description
Problem
When using style=form, explode=false for query parameters containing array values where an element itself contains a comma, BindQueryParameter cannot correctly deserialize the value.
Per the OpenAPI 3.0 spec, the serialized form should be:
value: ["a", "b", "c,d"]
query: search_term=a,b,c%2Cd
Delimiter commas are literal, and commas within values are percent-encoded as %2C.
What happens
BindQueryParameter receives url.Values, which Go's HTTP stack has already URL-decoded. By the time the runtime sees the value, %2C has been decoded back to ,, making it indistinguishable from the delimiter commas:
// Go's net/http parses "search_term=a,b,c%2Cd" into:
// url.Values{"search_term": ["a,b,c,d"]}
//
// BindQueryParameter then does:
// strings.Split("a,b,c,d", ",") → ["a", "b", "c", "d"] // 4 elements, expected 3Client side is fixed
The client side of this was fixed in oapi-codegen/oapi-codegen#2184 — StyleParamWithLocation correctly produces search_term=a,b,c%2Cd (individual values are url.QueryEscape'd before joining with literal comma delimiters). The generated client template was updated to preserve these raw fragments instead of round-tripping through url.ParseQuery/url.Values.Encode().
Suggested fix
To fix the server side, BindQueryParameter (or a new variant) would need access to the raw, undecoded query string (r.URL.RawQuery) rather than url.Values. It could then:
- Extract the raw parameter value (splitting on
&and=without decoding) - Split on literal
,to get the individual encoded parts - URL-decode each part individually
This would correctly yield ["a", "b", "c,d"].
This would also require changes to the server templates in oapi-codegen to pass the raw query string instead of (or in addition to) url.Values.
Related
- Using explode=false in query string doesn't work properly oapi-codegen#2183 — original bug report
- add tests for https://github.com/oapi-codegen/oapi-codegen/issues/2183 oapi-codegen#2184 — PR with client-side fix and test