Skip to content

Commit c322d1a

Browse files
TelpeNightmromaszewiczclaude
authored
add tests for #2183 (#2184)
* add tests for #2183 * fix(client): preserve literal commas in form/explode=false query params The generated client code was round-tripping styled query parameter fragments through url.ParseQuery + url.Values.Encode(), which re-encoded comma delimiters as %2C. Per the OpenAPI spec, form/explode=false arrays should use literal commas as delimiters (e.g. color=blue,black,brown). Change the client template to collect pre-encoded fragments from StyleParamWithLocation and join them directly, bypassing the re-encoding. Also moves the issue-2183 test to internal/test/issues/issue-2183/, extends it with explode=true and multi-param cases, and documents the remaining server-side limitation (oapi-codegen/runtime#91) for values containing embedded commas. Fixes #2183 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Regenerate affected boilerplate * Make sure to URL encode parameter names * Use non-deprecated runtime code * Update runtime and unstub test This exercises all the test cases in the bug. I will do a followup commit to fix all parameter handling. * Defer client parameter styling to runtime The split partial styling between client and runtime causes problems, so just have runtime do all of the work. --------- Co-authored-by: Marcin Romaszewicz <marcinr@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ddd9e90 commit c322d1a

File tree

13 files changed

+250
-128
lines changed

13 files changed

+250
-128
lines changed

examples/generate/serverurls/gen.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/petstore-expanded/petstore-client.gen.go

Lines changed: 14 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/test/any_of/param/param.gen.go

Lines changed: 14 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/test/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ require (
1515
github.com/labstack/echo/v4 v4.15.1
1616
github.com/oapi-codegen/nullable v1.1.0
1717
github.com/oapi-codegen/oapi-codegen/v2 v2.0.0-00010101000000-000000000000
18-
github.com/oapi-codegen/runtime v1.2.0
18+
github.com/oapi-codegen/runtime v1.3.1
1919
github.com/oapi-codegen/testutil v1.1.0
2020
github.com/stretchr/testify v1.11.1
2121
gopkg.in/yaml.v2 v2.4.0

internal/test/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
180180
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
181181
github.com/oapi-codegen/nullable v1.1.0 h1:eAh8JVc5430VtYVnq00Hrbpag9PFRGWLjxR1/3KntMs=
182182
github.com/oapi-codegen/nullable v1.1.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY=
183-
github.com/oapi-codegen/runtime v1.2.0 h1:RvKc1CVS1QeKSNzO97FBQbSMZyQ8s6rZd+LpmzwHMP4=
184-
github.com/oapi-codegen/runtime v1.2.0/go.mod h1:Y7ZhmmlE8ikZOmuHRRndiIm7nf3xcVv+YMweKgG1DT0=
183+
github.com/oapi-codegen/runtime v1.3.1 h1:RgDY6J4OGQLbRXhG/Xpt3vSVqYpHQS7hN4m85+5xB9g=
184+
github.com/oapi-codegen/runtime v1.3.1/go.mod h1:kOdeacKy7t40Rclb1je37ZLFboFxh+YLy0zaPCMibPY=
185185
github.com/oapi-codegen/testutil v1.1.0 h1:EufqpNg43acR3qzr3ObhXmWg3Sl2kwtRnUN5GYY4d5g=
186186
github.com/oapi-codegen/testutil v1.1.0/go.mod h1:ttCaYbHvJtHuiyeBF0tPIX+4uhEPTeizXKx28okijLw=
187187
github.com/oasdiff/yaml v0.0.0-20260313112342-a3ea61cb4d4c h1:7ACFcSaQsrWtrH4WHHfUqE1C+f8r2uv8KGaW0jTNjus=

internal/test/issues/issue-2031/prefer/issue2031.gen.go

Lines changed: 12 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package issue2183
2+
3+
import (
4+
"reflect"
5+
"strings"
6+
"testing"
7+
8+
"github.com/oapi-codegen/runtime"
9+
)
10+
11+
func TestQueryCommunication(t *testing.T) {
12+
13+
type ParamDefinition struct {
14+
style string
15+
explode bool
16+
paramName string
17+
value any
18+
}
19+
20+
testCases := []struct {
21+
Name string
22+
// Params defines the query parameters to serialize and deserialize.
23+
Params []ParamDefinition
24+
// SpecQuery is the expected raw query string per the OpenAPI spec.
25+
SpecQuery string
26+
}{
27+
{
28+
Name: "explode=false",
29+
Params: []ParamDefinition{{
30+
style: "form",
31+
explode: false,
32+
paramName: "color",
33+
value: []string{"blue", "black", "brown"},
34+
}},
35+
// https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#style-examples
36+
SpecQuery: "color=blue,black,brown",
37+
},
38+
{
39+
Name: "explode=false;commas",
40+
Params: []ParamDefinition{{
41+
style: "form",
42+
explode: false,
43+
paramName: "search_term",
44+
value: []string{"a", "b", "c,d"},
45+
}},
46+
SpecQuery: "search_term=a,b,c%2Cd",
47+
},
48+
{
49+
Name: "explode=true",
50+
Params: []ParamDefinition{{
51+
style: "form",
52+
explode: true,
53+
paramName: "color",
54+
value: []string{"blue", "black", "brown"},
55+
}},
56+
SpecQuery: "color=blue&color=black&color=brown",
57+
},
58+
{
59+
Name: "multiple params",
60+
Params: []ParamDefinition{
61+
{
62+
style: "form",
63+
explode: false,
64+
paramName: "color",
65+
value: []string{"blue", "black"},
66+
},
67+
{
68+
style: "form",
69+
explode: false,
70+
paramName: "size",
71+
value: []string{"s", "m", "l"},
72+
},
73+
},
74+
SpecQuery: "color=blue,black&size=s,m,l",
75+
},
76+
}
77+
78+
for _, tc := range testCases {
79+
t.Run(tc.Name, func(t *testing.T) {
80+
81+
// rawQueryFragments collects pre-encoded query fragments from
82+
// styled parameters, matching the generated client pattern.
83+
var rawQueryFragments []string
84+
85+
for _, param := range tc.Params {
86+
87+
// following code equivalent to generated client (after fix)
88+
queryFrag, err := runtime.StyleParamWithOptions(param.style, param.explode, param.paramName, param.value, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery})
89+
if err != nil {
90+
t.Fatal(err)
91+
}
92+
rawQueryFragments = append(rawQueryFragments, queryFrag)
93+
}
94+
95+
rawQuery := strings.Join(rawQueryFragments, "&")
96+
t.Logf("client query: %s", rawQuery)
97+
if tc.SpecQuery != "" && rawQuery != tc.SpecQuery {
98+
t.Errorf("spec query: expected %q, got %q", tc.SpecQuery, rawQuery)
99+
}
100+
101+
// following code equivalent to generated server
102+
for _, param := range tc.Params {
103+
104+
dest := reflect.New(reflect.TypeOf(param.value))
105+
err := runtime.BindRawQueryParameter(param.style, param.explode, true, param.paramName, rawQuery, dest.Interface())
106+
if err != nil {
107+
t.Error(err)
108+
} else if !reflect.DeepEqual(dest.Elem().Interface(), param.value) {
109+
t.Errorf("expecting %v, got %v", param.value, dest.Elem().Interface())
110+
}
111+
112+
}
113+
114+
})
115+
}
116+
}

internal/test/name_conflict_resolution/name_conflict_resolution.gen.go

Lines changed: 12 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)