@@ -21,31 +21,60 @@ func (value Paths) Validate(ctx context.Context) error {
21
21
pathItem = value [path ]
22
22
}
23
23
24
- normalizedPath , pathParamsCount := normalizeTemplatedPath (path )
24
+ normalizedPath , _ , varsInPath := normalizeTemplatedPath (path )
25
25
if oldPath , ok := normalizedPaths [normalizedPath ]; ok {
26
26
return fmt .Errorf ("conflicting paths %q and %q" , path , oldPath )
27
27
}
28
28
normalizedPaths [path ] = path
29
29
30
- var globalCount uint
30
+ var commonParams [] string
31
31
for _ , parameterRef := range pathItem .Parameters {
32
32
if parameterRef != nil {
33
33
if parameter := parameterRef .Value ; parameter != nil && parameter .In == ParameterInPath {
34
- globalCount ++
34
+ commonParams = append ( commonParams , parameter . Name )
35
35
}
36
36
}
37
37
}
38
38
for method , operation := range pathItem .Operations () {
39
- var count uint
39
+ var setParams [] string
40
40
for _ , parameterRef := range operation .Parameters {
41
41
if parameterRef != nil {
42
42
if parameter := parameterRef .Value ; parameter != nil && parameter .In == ParameterInPath {
43
- count ++
43
+ setParams = append ( setParams , parameter . Name )
44
44
}
45
45
}
46
46
}
47
- if count + globalCount != pathParamsCount {
48
- return fmt .Errorf ("operation %s %s must define exactly all path parameters" , method , path )
47
+ if expected := len (setParams ) + len (commonParams ); expected != len (varsInPath ) {
48
+ expected -= len (varsInPath )
49
+ if expected < 0 {
50
+ expected *= - 1
51
+ }
52
+ missing := make (map [string ]struct {}, expected )
53
+ definedParams := append (setParams , commonParams ... )
54
+ for _ , name := range definedParams {
55
+ if _ , ok := varsInPath [name ]; ! ok {
56
+ missing [name ] = struct {}{}
57
+ }
58
+ }
59
+ for name := range varsInPath {
60
+ got := false
61
+ for _ , othername := range definedParams {
62
+ if othername == name {
63
+ got = true
64
+ break
65
+ }
66
+ }
67
+ if ! got {
68
+ missing [name ] = struct {}{}
69
+ }
70
+ }
71
+ if len (missing ) != 0 {
72
+ missings := make ([]string , 0 , len (missing ))
73
+ for name := range missing {
74
+ missings = append (missings , name )
75
+ }
76
+ return fmt .Errorf ("operation %s %s must define exactly all path parameters (missing: %v)" , method , path , missings )
77
+ }
49
78
}
50
79
}
51
80
@@ -75,53 +104,61 @@ func (paths Paths) Find(key string) *PathItem {
75
104
return pathItem
76
105
}
77
106
78
- normalizedPath , expected := normalizeTemplatedPath (key )
107
+ normalizedPath , expected , _ := normalizeTemplatedPath (key )
79
108
for path , pathItem := range paths {
80
- pathNormalized , got := normalizeTemplatedPath (path )
109
+ pathNormalized , got , _ := normalizeTemplatedPath (path )
81
110
if got == expected && pathNormalized == normalizedPath {
82
111
return pathItem
83
112
}
84
113
}
85
114
return nil
86
115
}
87
116
88
- func normalizeTemplatedPath (path string ) (string , uint ) {
117
+ func normalizeTemplatedPath (path string ) (string , uint , map [ string ] struct {} ) {
89
118
if strings .IndexByte (path , '{' ) < 0 {
90
- return path , 0
119
+ return path , 0 , nil
91
120
}
92
121
93
- var buf strings.Builder
94
- buf .Grow (len (path ))
122
+ var buffTpl strings.Builder
123
+ buffTpl .Grow (len (path ))
95
124
96
125
var (
97
126
cc rune
98
127
count uint
99
128
isVariable bool
129
+ vars = make (map [string ]struct {})
130
+ buffVar strings.Builder
100
131
)
101
132
for i , c := range path {
102
133
if isVariable {
103
134
if c == '}' {
104
- // End path variables
135
+ // End path variable
136
+ isVariable = false
137
+
138
+ vars [buffVar .String ()] = struct {}{}
139
+ buffVar = strings.Builder {}
140
+
105
141
// First append possible '*' before this character
106
142
// The character '}' will be appended
107
143
if i > 0 && cc == '*' {
108
- buf .WriteRune (cc )
144
+ buffTpl .WriteRune (cc )
109
145
}
110
- isVariable = false
111
146
} else {
112
- // Skip this character
147
+ buffVar . WriteRune ( c )
113
148
continue
114
149
}
150
+
115
151
} else if c == '{' {
116
152
// Begin path variable
117
- // The character '{' will be appended
118
153
isVariable = true
154
+
155
+ // The character '{' will be appended
119
156
count ++
120
157
}
121
158
122
159
// Append the character
123
- buf .WriteRune (c )
160
+ buffTpl .WriteRune (c )
124
161
cc = c
125
162
}
126
- return buf .String (), count
163
+ return buffTpl .String (), count , vars
127
164
}
0 commit comments