-
-
Notifications
You must be signed in to change notification settings - Fork 46
Description
Bug Description
BindStyledParameterWithOptions does not strip the style prefix when binding primitive (non-struct, non-slice, non-map) values with label or matrix styles. This causes server-side parameter binding to fail with parse errors for these style/type combinations.
Root Cause
In bindparam.go, BindStyledParameterWithOptions has three code paths:
- Struct/Map (line ~118): calls
splitStyledParameter()which correctly strips style prefixes - Slice (line ~129): calls
splitStyledParameter()which correctly strips style prefixes - Primitive (line ~156): calls
BindStringToObject(value, dest)directly without stripping the style prefix
For simple and form styles, primitives have no prefix so this works fine. But for label and matrix styles, the styled value still contains its prefix when passed to BindStringToObject.
Reproduction
Label style
The client correctly serializes an int32 value 5 as .5 (per OpenAPI 3.0 label style). On the server:
```go
// value = ".5" (with leading dot)
BindStyledParameterWithOptions("label", "param", ".5", &dest, opts)
// Falls through to: BindStringToObject(".5", &int32)
// Error: strconv.ParseInt: parsing ".5": invalid syntax
```
Matrix style
The client serializes 5 as ;param=5. On the server:
```go
// value = ";param=5"
BindStyledParameterWithOptions("matrix", "param", ";param=5", &dest, opts)
// Falls through to: BindStringToObject(";param=5", &int32)
// Error: strconv.ParseInt: parsing ";param=5": invalid syntax
```
Why arrays/objects are unaffected
For arrays and objects, splitStyledParameter() is called, which correctly strips the . prefix (label) and ;name= prefix (matrix) before binding individual parts. The bug is only in the primitive code path which bypasses splitStyledParameter entirely.
Affected combinations
| Style | Explode | Primitive | Array | Object |
|---|---|---|---|---|
| simple | false | OK | OK | OK |
| simple | true | OK | OK | OK |
| label | false | BROKEN | OK | OK |
| label | true | BROKEN | OK | OK |
| matrix | false | BROKEN | OK | OK |
| matrix | true | BROKEN | OK | OK |
Suggested Fix
Before the final BindStringToObject(value, dest) call in BindStyledParameterWithOptions, strip the style prefix for primitive values:
```go
// Strip style prefix for primitive values.
switch style {
case "label":
if !strings.HasPrefix(value, ".") {
return fmt.Errorf("invalid format for label parameter '%s', should start with '.'", paramName)
}
value = value[1:]
case "matrix":
prefix := ";" + paramName + "="
if !strings.HasPrefix(value, prefix) {
return fmt.Errorf("expected parameter '%s' to start with %s", paramName, prefix)
}
value = strings.TrimPrefix(value, prefix)
}
return BindStringToObject(value, dest)
```
How this was discovered
While building a comprehensive parameter permutation test suite for oapi-codegen, testing every combination of parameter location x style x explode x value type (primitive, array, object) via client-to-server round-trips. The label and matrix primitive tests fail with 400 errors on the server side. The tests are currently skipped with a note referencing this bug.
Environment
github.com/oapi-codegen/runtimev1.2.0- Go 1.24
- Tested with Echo server framework (but the bug is in the runtime library, framework-independent)