@@ -20,16 +20,38 @@ type QueryParamParser struct {
20
20
// Errors is the set of errors to return via the API. If the length
21
21
// of this set is 0, there are no errors!.
22
22
Errors []codersdk.ValidationError
23
+ // Parsed is a map of all query params that were parsed. This is useful
24
+ // for checking if extra query params were passed in.
25
+ Parsed map [string ]bool
23
26
}
24
27
25
28
func NewQueryParamParser () * QueryParamParser {
26
29
return & QueryParamParser {
27
30
Errors : []codersdk.ValidationError {},
31
+ Parsed : map [string ]bool {},
28
32
}
29
33
}
30
34
35
+ // ErrorExcessParams checks if any query params were passed in that were not
36
+ // parsed. If so, it adds an error to the parser as these values are not valid
37
+ // query parameters.
38
+ func (p * QueryParamParser ) ErrorExcessParams (values url.Values ) {
39
+ for k := range values {
40
+ if _ , ok := p .Parsed [k ]; ! ok {
41
+ p .Errors = append (p .Errors , codersdk.ValidationError {
42
+ Field : k ,
43
+ Detail : fmt .Sprintf ("Query param %q is not a valid query param" , k ),
44
+ })
45
+ }
46
+ }
47
+ }
48
+
49
+ func (p * QueryParamParser ) addParsed (key string ) {
50
+ p .Parsed [key ] = true
51
+ }
52
+
31
53
func (p * QueryParamParser ) Int (vals url.Values , def int , queryParam string ) int {
32
- v , err := parseQueryParam (vals , strconv .Atoi , def , queryParam )
54
+ v , err := parseQueryParam (p , vals , strconv .Atoi , def , queryParam )
33
55
if err != nil {
34
56
p .Errors = append (p .Errors , codersdk.ValidationError {
35
57
Field : queryParam ,
@@ -40,14 +62,16 @@ func (p *QueryParamParser) Int(vals url.Values, def int, queryParam string) int
40
62
}
41
63
42
64
func (p * QueryParamParser ) UUIDorMe (vals url.Values , def uuid.UUID , me uuid.UUID , queryParam string ) uuid.UUID {
43
- if vals .Get (queryParam ) == "me" {
44
- return me
45
- }
46
- return p .UUID (vals , def , queryParam )
65
+ return ParseCustom (p , vals , def , queryParam , func (v string ) (uuid.UUID , error ) {
66
+ if v == "me" {
67
+ return me , nil
68
+ }
69
+ return uuid .Parse (v )
70
+ })
47
71
}
48
72
49
73
func (p * QueryParamParser ) UUID (vals url.Values , def uuid.UUID , queryParam string ) uuid.UUID {
50
- v , err := parseQueryParam (vals , uuid .Parse , def , queryParam )
74
+ v , err := parseQueryParam (p , vals , uuid .Parse , def , queryParam )
51
75
if err != nil {
52
76
p .Errors = append (p .Errors , codersdk.ValidationError {
53
77
Field : queryParam ,
@@ -58,7 +82,7 @@ func (p *QueryParamParser) UUID(vals url.Values, def uuid.UUID, queryParam strin
58
82
}
59
83
60
84
func (p * QueryParamParser ) UUIDs (vals url.Values , def []uuid.UUID , queryParam string ) []uuid.UUID {
61
- v , err := parseQueryParam (vals , func (v string ) ([]uuid.UUID , error ) {
85
+ v , err := parseQueryParam (p , vals , func (v string ) ([]uuid.UUID , error ) {
62
86
var badValues []string
63
87
strs := strings .Split (v , "," )
64
88
ids := make ([]uuid.UUID , 0 , len (strs ))
@@ -85,15 +109,15 @@ func (p *QueryParamParser) UUIDs(vals url.Values, def []uuid.UUID, queryParam st
85
109
return v
86
110
}
87
111
88
- func (* QueryParamParser ) String (vals url.Values , def string , queryParam string ) string {
89
- v , _ := parseQueryParam (vals , func (v string ) (string , error ) {
112
+ func (p * QueryParamParser ) String (vals url.Values , def string , queryParam string ) string {
113
+ v , _ := parseQueryParam (p , vals , func (v string ) (string , error ) {
90
114
return v , nil
91
115
}, def , queryParam )
92
116
return v
93
117
}
94
118
95
- func (* QueryParamParser ) Strings (vals url.Values , def []string , queryParam string ) []string {
96
- v , _ := parseQueryParam (vals , func (v string ) ([]string , error ) {
119
+ func (p * QueryParamParser ) Strings (vals url.Values , def []string , queryParam string ) []string {
120
+ v , _ := parseQueryParam (p , vals , func (v string ) ([]string , error ) {
97
121
if v == "" {
98
122
return []string {}, nil
99
123
}
@@ -105,7 +129,7 @@ func (*QueryParamParser) Strings(vals url.Values, def []string, queryParam strin
105
129
// ParseCustom has to be a function, not a method on QueryParamParser because generics
106
130
// cannot be used on struct methods.
107
131
func ParseCustom [T any ](parser * QueryParamParser , vals url.Values , def T , queryParam string , parseFunc func (v string ) (T , error )) T {
108
- v , err := parseQueryParam (vals , parseFunc , def , queryParam )
132
+ v , err := parseQueryParam (parser , vals , parseFunc , def , queryParam )
109
133
if err != nil {
110
134
parser .Errors = append (parser .Errors , codersdk.ValidationError {
111
135
Field : queryParam ,
@@ -115,7 +139,8 @@ func ParseCustom[T any](parser *QueryParamParser, vals url.Values, def T, queryP
115
139
return v
116
140
}
117
141
118
- func parseQueryParam [T any ](vals url.Values , parse func (v string ) (T , error ), def T , queryParam string ) (T , error ) {
142
+ func parseQueryParam [T any ](parser * QueryParamParser , vals url.Values , parse func (v string ) (T , error ), def T , queryParam string ) (T , error ) {
143
+ parser .addParsed (queryParam )
119
144
if ! vals .Has (queryParam ) || vals .Get (queryParam ) == "" {
120
145
return def , nil
121
146
}
0 commit comments