forked from pb33f/libopenapi-validator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheader_parameters.go
162 lines (141 loc) · 4.82 KB
/
header_parameters.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT
package parameters
import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/pb33f/libopenapi/datamodel/high/base"
v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
"github.com/pb33f/libopenapi-validator/errors"
"github.com/pb33f/libopenapi-validator/helpers"
"github.com/pb33f/libopenapi-validator/paths"
)
func (v *paramValidator) ValidateHeaderParams(request *http.Request) (bool, []*errors.ValidationError) {
pathItem, errs, foundPath := paths.FindPath(request, v.document)
if len(errs) > 0 {
return false, errs
}
return v.ValidateHeaderParamsWithPathItem(request, pathItem, foundPath)
}
func (v *paramValidator) ValidateHeaderParamsWithPathItem(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) {
if pathItem == nil {
return false, []*errors.ValidationError{{
ValidationType: helpers.ParameterValidationPath,
ValidationSubType: "missing",
Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path),
Reason: fmt.Sprintf("The %s request contains a path of '%s' "+
"however that path, or the %s method for that path does not exist in the specification",
request.Method, request.URL.Path, request.Method),
SpecLine: -1,
SpecCol: -1,
HowToFix: errors.HowToFixPath,
}}
}
// extract params for the operation
params := helpers.ExtractParamsForOperation(request, pathItem)
var validationErrors []*errors.ValidationError
seenHeaders := make(map[string]bool)
for _, p := range params {
if p.In == helpers.Header {
seenHeaders[strings.ToLower(p.Name)] = true
if param := request.Header.Get(p.Name); param != "" {
var sch *base.Schema
if p.Schema != nil {
sch = p.Schema.Schema()
}
pType := sch.Type
for _, ty := range pType {
switch ty {
case helpers.Integer, helpers.Number:
if _, err := strconv.ParseFloat(param, 64); err != nil {
validationErrors = append(validationErrors,
errors.InvalidHeaderParamNumber(p, strings.ToLower(param), sch))
break
}
// check if the param is within the enum
if sch.Enum != nil {
matchFound := false
for _, enumVal := range sch.Enum {
if strings.TrimSpace(param) == fmt.Sprint(enumVal.Value) {
matchFound = true
break
}
}
if !matchFound {
validationErrors = append(validationErrors,
errors.IncorrectCookieParamEnum(p, strings.ToLower(param), sch))
}
}
case helpers.Boolean:
if _, err := strconv.ParseBool(param); err != nil {
validationErrors = append(validationErrors,
errors.IncorrectHeaderParamBool(p, strings.ToLower(param), sch))
}
case helpers.Object:
// check if the header is default encoded or not
var encodedObj map[string]interface{}
// we have found our header, check the explode type.
if p.IsDefaultHeaderEncoding() {
encodedObj = helpers.ConstructMapFromCSV(param)
} else {
if p.IsExploded() { // only option is to be exploded for KV extraction.
encodedObj = helpers.ConstructKVFromCSV(param)
}
}
if len(encodedObj) == 0 {
validationErrors = append(validationErrors,
errors.HeaderParameterCannotBeDecoded(p, strings.ToLower(param)))
break
}
// if a schema was extracted
if sch != nil {
validationErrors = append(validationErrors,
ValidateParameterSchema(sch,
encodedObj,
"",
"Header parameter",
"The header parameter",
p.Name,
helpers.ParameterValidation,
helpers.ParameterValidationQuery, v.options)...)
}
case helpers.Array:
if !p.IsExploded() { // only unexploded arrays are supported for cookie params
if sch.Items.IsA() {
validationErrors = append(validationErrors,
ValidateHeaderArray(sch, p, param)...)
}
}
case helpers.String:
// check if the schema has an enum, and if so, match the value against one of
// the defined enum values.
if sch.Enum != nil {
matchFound := false
for _, enumVal := range sch.Enum {
if strings.TrimSpace(param) == fmt.Sprint(enumVal.Value) {
matchFound = true
break
}
}
if !matchFound {
validationErrors = append(validationErrors,
errors.IncorrectHeaderParamEnum(p, strings.ToLower(param), sch))
}
}
}
}
} else {
if p.Required != nil && *p.Required {
validationErrors = append(validationErrors, errors.HeaderParameterMissing(p))
}
}
}
}
errors.PopulateValidationErrors(validationErrors, request, pathValue)
if len(validationErrors) > 0 {
return false, validationErrors
}
return true, nil
}