Addresses oapi-codegen/oapi-codegen#2051
Go's net/url encodes a space in query strings as '+' (the form-urlencoded
convention), which is not RFC 3986 compliant. Some servers (e.g. OData
endpoints expecting ?filter=name%20eq%20'x') reject '+'-encoded spaces with
400 Bad Request, while others require '+'. Since neither encoding is
universally correct, this makes the behavior configurable rather than
changing the default.
Introduce a QueryEncoder interface (a single EscapeQueryValue method) with two
built-in implementations in a new encoder.go: NetURLQueryEncoder (the default,
'+' for space, preserving current behavior) and RFC3986QueryEncoder ('%20' for
space). A package-level DefaultQueryEncoder (mirroring http.DefaultClient) lets
callers opt in during program initialization. Names and map keys are escaped as
values with allowReserved=false, which allowReserved never applies to.
All query escaping in styleparam.go and deepobject.go now routes through
DefaultQueryEncoder, so both styled and deepObject query parameters honor the
choice. Path escaping and x-www-form-urlencoded request bodies are left
unchanged, where '+' for a space is the correct, media-type-defined behavior.
Documented under the README "Encoding" section; tests in encoder_test.go.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Addresses oapi-codegen/oapi-codegen#2051
Go's net/url encodes a space in query strings as '+' (the form-urlencoded convention), which is not RFC 3986 compliant. Some servers (e.g. OData endpoints expecting ?filter=name%20eq%20'x') reject '+'-encoded spaces with 400 Bad Request, while others require '+'. Since neither encoding is universally correct, this makes the behavior configurable rather than changing the default.
Introduce a QueryEncoder interface with two built-in implementations in a new encoder.go: NetURLQueryEncoder (the default, '+' for space, preserving current behavior) and RFC3986QueryEncoder ('%20' for space). A package-level DefaultQueryEncoder (mirroring http.DefaultClient) lets callers opt in during program initialization.
All query escaping in styleparam.go and deepobject.go now routes through DefaultQueryEncoder, so both styled and deepObject query parameters honor the choice. Path escaping and x-www-form-urlencoded request bodies are left unchanged, where '+' for a space is the correct, media-type-defined behavior.
Documented under the README "Encoding" section; tests in encoder_test.go.