Skip to content

BindQueryParameter cannot distinguish delimiter commas from literal commas in form/explode=false values #91

@mromaszewicz

Description

@mromaszewicz

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 3

Client side is fixed

The client side of this was fixed in oapi-codegen/oapi-codegen#2184StyleParamWithLocation 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:

  1. Extract the raw parameter value (splitting on & and = without decoding)
  2. Split on literal , to get the individual encoded parts
  3. 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

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