Skip to content

Request parameter validation fails due to url encoding #1105

@pimlie

Description

@pimlie

I am using a base64 encoded value as path parameter in my api. Base64 uses the = char as padding which needs to be encoded to %3D in urls. Note that URL.Path points to the unencoded path (fe =), and URL.RawPath points to the url encoded path (fe %3D).

If this repro using vanilla gorillamux is correct, then it seems not to be an issue with gorillamux as that correctly returns the = path: https://play.golang.com/p/4jrI69ptaof

But when using router.FindRoute from kin-openapi/gorillamux the encoded %3D path is returned which causes the validation to fail. I've looked at the FindRoute code but I don't see anything obviously wrong that could cause the encoded path value to be returned...

Any idea why this happens? Do I maybe need to unencode the path myself?

package main

import (
        "context"
        "fmt"
        "net/http"

        "github.com/getkin/kin-openapi/openapi3"
        "github.com/getkin/kin-openapi/openapi3filter"
        "github.com/getkin/kin-openapi/routers/gorillamux"
)

const testSchema = `openapi: 3.0.0
info:
  title: ''
  version: 0.0.1
paths:
  /some/path/{token}:
    parameters:
      - $ref: '#/components/parameters/Token'
    post:
      responses:
components:
  parameters:
    Token:
      name: token
      in: path
      required: true
      schema:
        type: string
        pattern: ^[a-zA-Z0-9\-_=]+$
`

func main() {
        swagger, err := openapi3.NewLoader().LoadFromData([]byte(testSchema))
        if err != nil {
          fmt.Println("Swagger Error", err)
          return
        }

        router, err := gorillamux.NewRouter(swagger)
        if err != nil {
          fmt.Println("Router Error", err)
          return
        }
        req, err := http.NewRequest(http.MethodPost, "/some/path/asdf%3D", nil)
        if err != nil {
          fmt.Println("Request Error", err)
          return
        }
        fmt.Println("path", req.URL.Path, req.URL.RawPath)
        route, pathParams, err := router.FindRoute(req)
        if err != nil {
          fmt.Println("FindRoute Error", err)
          return
        }
        fmt.Println("route", route.Path)
        fmt.Println("pathParameters", pathParams)

        requestValidationInput := &openapi3filter.RequestValidationInput{
                Request:    req,
                PathParams: pathParams,
                Route:      route,
        }

        err = openapi3filter.ValidateRequest(context.TODO(), requestValidationInput)
        if err == nil {
                fmt.Println("Valid")
        } else {
                fmt.Println("NOT valid", err)
        }
}

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