Skip to content

Label and matrix scalar string paths split delimiter-bearing values #175

Closed

Description

@tgauda

BindStyledParameterWithOptions (v1.8.0) rejects valid string scalar path
values containing delimiters under label and matrix styles. This appears
to be the remaining styled scalar branch of #114 — simple-style strings now
preserve commas, but the label/matrix primitive branch still runs collection
splitting and rejects multi-part results.

Notably, the runtime's own encoder percent-encodes the delimiter correctly
(%2C, %3B), and net/http.ServeMux.PathValue decodes the segment before
binding (ValueIsUnescaped: true) — so a client that does everything right
still cannot roundtrip its own valid scalar.

Reproduction (github.com/oapi-codegen/runtime v1.8.0, Go 1.27.3,
linux/arm64):

package main

import (
     "fmt"
     "net/url"

     "github.com/oapi-codegen/runtime"
)

func main() {
     for _, tc := range []struct {
             style   string
             explode bool
             value   string
     }{
             {"simple", false, "big,red"},
             {"label", false, "big,red"},
             {"matrix", false, "big,red"},
             {"label", true, "big.red"},
             {"matrix", true, "big;red"},
     } {
             encoded, err := runtime.StyleParamWithOptions(tc.style, tc.explode, "color", tc.value, runtime.StylePa
ramOptions{ParamLocation: runtime.ParamLocationPath})
             if err != nil {
                     panic(err)
             }
             // net/http ServeMux.PathValue has already URL-decoded this segment.
             decoded, err := url.PathUnescape(encoded)
             if err != nil {
                     panic(err)
             }
             var got string
             err = runtime.BindStyledParameterWithOptions(tc.style, "color", decoded, &got, runtime.BindStyledParam
eterOptions{
                     ParamLocation: runtime.ParamLocationPath,
                     Explode:      tc.explode,
                     Required:     true,
                     ValueIsUnescaped: true,
             })
             fmt.Printf("style=%s explode=%t input=%q encoded=%q got=%q err=%v\n",
                     tc.style, tc.explode, tc.value, encoded, got, err)
     }
}

Run with:

mkdir repro && cd repro
go mod init repro
go get github.com/oapi-codegen/runtime@v1.8.0
# save the program above as main.go
go run .

Actual output:

style=simple explode=false input="big,red" encoded="big%2Cred" got="big,red" err=<nil>
style=label explode=false input="big,red" encoded=".big%2Cred" got="" err=parameter 'color': expected si
ngle value, got 2 parts
style=matrix explode=false input="big,red" encoded=";color=big%2Cred" got="" err=parameter 'color': expe
cted single value, got 2 parts
style=label explode=true input="big.red" encoded=".big.red" got="" err=parameter 'color': expected singl
e value, got 2 parts
style=matrix explode=true input="big;red" encoded=";color=big%3Bred" got="" err=parameter 'color': expec
ted single value, got 2 parts

Expected: every case binds with got equal to the input and no error — the
encoder escapes the delimiter, the router decodes it, and a scalar's value is
data, not structure.

Notes: the primitive branch for label/matrix in bindparam.go calls
splitStyledParameter and requires exactly one part; the #114 fix (skip
splitting for primitives under simple) appears not to have been applied to
this branch, where prefix stripping still occurs. The reproduction was
verified against v1.8.0 with the output above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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