Skip to content

Commit

Permalink
pathItem as parameter to avoid race conditions
Browse files Browse the repository at this point in the history
Signed-off-by: Emilien Puget <[email protected]>
  • Loading branch information
emilien-puget committed Jul 8, 2024
1 parent bc63c2f commit e720fcd
Show file tree
Hide file tree
Showing 17 changed files with 638 additions and 899 deletions.
22 changes: 2 additions & 20 deletions parameters/cookie_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,14 @@ import (
"fmt"
"github.com/pb33f/libopenapi-validator/errors"
"github.com/pb33f/libopenapi-validator/helpers"
"github.com/pb33f/libopenapi-validator/paths"
"github.com/pb33f/libopenapi/datamodel/high/base"
v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
"net/http"
"strconv"
"strings"
)

func (v *paramValidator) ValidateCookieParams(request *http.Request) (bool, []*errors.ValidationError) {

// find path
var pathItem *v3.PathItem
var foundPath string
var errs []*errors.ValidationError

if v.pathItem == nil {
pathItem, errs, foundPath = paths.FindPath(request, v.document)
if pathItem == nil || errs != nil {
v.errors = errs
return false, errs
}
} else {
pathItem = v.pathItem
foundPath = v.pathValue
}

func (v *paramValidator) ValidateCookieParams(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) {
// extract params for the operation
var params = helpers.ExtractParamsForOperation(request, pathItem)
var validationErrors []*errors.ValidationError
Expand Down Expand Up @@ -125,7 +107,7 @@ func (v *paramValidator) ValidateCookieParams(request *http.Request) (bool, []*e
}
}

errors.PopulateValidationErrors(validationErrors, request, foundPath)
errors.PopulateValidationErrors(validationErrors, request, pathValue)

if len(validationErrors) > 0 {
return false, validationErrors
Expand Down
124 changes: 53 additions & 71 deletions parameters/cookie_parameters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ package parameters

import (
"github.com/pb33f/libopenapi"
"github.com/pb33f/libopenapi-validator/paths"
"github.com/stretchr/testify/assert"
"net/http"
"testing"
"github.com/pb33f/libopenapi-validator/paths"
)

func TestNewValidator_CookieNoPath(t *testing.T) {
Expand All @@ -26,14 +26,11 @@ paths:

doc, _ := libopenapi.NewDocument([]byte(spec))
m, _ := doc.BuildV3Model()
v := NewParameterValidator(&m.Model)

request, _ := http.NewRequest(http.MethodGet, "https://things.com/I/do/not/exist", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "1"})

valid, errors := v.ValidateCookieParams(request)

assert.False(t, valid)
_, errors, _ := paths.FindPath(request, &m.Model)
assert.Len(t, errors, 1)
assert.Equal(t, request.Method, errors[0].RequestMethod)
assert.Equal(t, request.URL.Path, errors[0].RequestPath)
Expand All @@ -59,8 +56,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "1"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand All @@ -85,8 +83,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "123.455"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand All @@ -111,8 +110,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "false"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.False(t, valid)
assert.Len(t, errors, 1)
Expand All @@ -138,8 +138,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "true"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand Down Expand Up @@ -168,8 +169,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "chicken"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand Down Expand Up @@ -198,8 +200,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "milk"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.False(t, valid)
assert.Len(t, errors, 1)
Expand Down Expand Up @@ -229,8 +232,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "12345"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.False(t, valid)
assert.Len(t, errors, 1)
Expand Down Expand Up @@ -263,8 +267,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "pink,true,number,2"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand Down Expand Up @@ -296,8 +301,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "pink,2,number,2"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.False(t, valid)
assert.Len(t, errors, 1)
Expand Down Expand Up @@ -325,8 +331,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "2,3,4"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand All @@ -353,8 +360,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "2,true,4,'hello'"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.False(t, valid)
assert.Len(t, errors, 2)
Expand All @@ -381,8 +389,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "true,false,true,false,true"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand All @@ -409,8 +418,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "true,1,hey,ho"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand All @@ -437,8 +447,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "true,false,pb33f,false,99.99"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.False(t, valid)
assert.Len(t, errors, 2)
Expand All @@ -465,8 +476,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "true,false,0,false,1"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.False(t, valid)
assert.Len(t, errors, 2)
Expand All @@ -492,8 +504,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "2"})

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.True(t, valid)
assert.Len(t, errors, 0)
Expand All @@ -519,40 +532,9 @@ paths:

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "2500"}) // too many dude.

valid, errors := v.ValidateCookieParams(request)

assert.False(t, valid)
assert.Len(t, errors, 1)
assert.Equal(t, "Instead of '2500', use one of the allowed values: '1, 2, 99'", errors[0].HowToFix)
}

func TestNewValidator_PresetPath(t *testing.T) {

spec := `openapi: 3.1.0
paths:
/burgers/beef:
get:
parameters:
- name: PattyPreference
in: cookie
required: true
schema:
type: integer
enum: [1, 2, 99]`

doc, _ := libopenapi.NewDocument([]byte(spec))
m, _ := doc.BuildV3Model()
v := NewParameterValidator(&m.Model)

request, _ := http.NewRequest(http.MethodGet, "https://things.com/burgers/beef", nil)
request.AddCookie(&http.Cookie{Name: "PattyPreference", Value: "2500"}) // too many dude.

// preset the path
path, _, pv := paths.FindPath(request, &m.Model)
v.SetPathItem(path, pv)

valid, errors := v.ValidateCookieParams(request)
pathItem, validationErrors, pathValue := paths.FindPath(request, &m.Model)
assert.Len(t, validationErrors, 0)
valid, errors := v.ValidateCookieParams(request, pathItem, pathValue)

assert.False(t, valid)
assert.Len(t, errors, 1)
Expand Down
20 changes: 2 additions & 18 deletions parameters/header_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,11 @@ import (

"github.com/pb33f/libopenapi-validator/errors"
"github.com/pb33f/libopenapi-validator/helpers"
"github.com/pb33f/libopenapi-validator/paths"
"github.com/pb33f/libopenapi/datamodel/high/base"
v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
)

func (v *paramValidator) ValidateHeaderParams(request *http.Request) (bool, []*errors.ValidationError) {
// find path
var pathItem *v3.PathItem
var specPath string
var errs []*errors.ValidationError
if v.pathItem == nil {
pathItem, errs, specPath = paths.FindPath(request, v.document)
if pathItem == nil || errs != nil {
v.errors = errs
return false, errs
}
} else {
pathItem = v.pathItem
specPath = v.pathValue
}

func (v *paramValidator) ValidateHeaderParams(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) {
// extract params for the operation
params := helpers.ExtractParamsForOperation(request, pathItem)

Expand Down Expand Up @@ -145,7 +129,7 @@ func (v *paramValidator) ValidateHeaderParams(request *http.Request) (bool, []*e
}
}

errors.PopulateValidationErrors(validationErrors, request, specPath)
errors.PopulateValidationErrors(validationErrors, request, pathValue)

if len(validationErrors) > 0 {
return false, validationErrors
Expand Down
Loading

0 comments on commit e720fcd

Please sign in to comment.