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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions