|
Packit Service |
3a6627 |
package openapi3
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
import (
|
|
Packit Service |
3a6627 |
"context"
|
|
Packit Service |
3a6627 |
"fmt"
|
|
Packit Service |
3a6627 |
"strings"
|
|
Packit Service |
3a6627 |
)
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
// Paths is specified by OpenAPI/Swagger standard version 3.0.
|
|
Packit Service |
3a6627 |
type Paths map[string]*PathItem
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
func (paths Paths) Validate(c context.Context) error {
|
|
Packit Service |
3a6627 |
normalizedPaths := make(map[string]string)
|
|
Packit Service |
3a6627 |
for path, pathItem := range paths {
|
|
Packit Service |
3a6627 |
if path == "" || path[0] != '/' {
|
|
Packit Service |
3a6627 |
return fmt.Errorf("path %q does not start with a forward slash (/)", path)
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
normalizedPath, pathParamsCount := normalizeTemplatedPath(path)
|
|
Packit Service |
3a6627 |
if oldPath, ok := normalizedPaths[normalizedPath]; ok {
|
|
Packit Service |
3a6627 |
return fmt.Errorf("conflicting paths %q and %q", path, oldPath)
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
normalizedPaths[path] = path
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
var globalCount uint
|
|
Packit Service |
3a6627 |
for _, parameterRef := range pathItem.Parameters {
|
|
Packit Service |
3a6627 |
if parameterRef != nil {
|
|
Packit Service |
3a6627 |
if parameter := parameterRef.Value; parameter != nil && parameter.In == ParameterInPath {
|
|
Packit Service |
3a6627 |
globalCount++
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
for method, operation := range pathItem.Operations() {
|
|
Packit Service |
3a6627 |
var count uint
|
|
Packit Service |
3a6627 |
for _, parameterRef := range operation.Parameters {
|
|
Packit Service |
3a6627 |
if parameterRef != nil {
|
|
Packit Service |
3a6627 |
if parameter := parameterRef.Value; parameter != nil && parameter.In == ParameterInPath {
|
|
Packit Service |
3a6627 |
count++
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
if count+globalCount != pathParamsCount {
|
|
Packit Service |
3a6627 |
return fmt.Errorf("operation %s %s must define exactly all path parameters", method, path)
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
if err := pathItem.Validate(c); err != nil {
|
|
Packit Service |
3a6627 |
return err
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
return nil
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
// Find returns a path that matches the key.
|
|
Packit Service |
3a6627 |
//
|
|
Packit Service |
3a6627 |
// The method ignores differences in template variable names (except possible "*" suffix).
|
|
Packit Service |
3a6627 |
//
|
|
Packit Service |
3a6627 |
// For example:
|
|
Packit Service |
3a6627 |
//
|
|
Packit Service |
3a6627 |
// paths := openapi3.Paths {
|
|
Packit Service |
3a6627 |
// "/person/{personName}": &openapi3.PathItem{},
|
|
Packit Service |
3a6627 |
// }
|
|
Packit Service |
3a6627 |
// pathItem := path.Find("/person/{name}")
|
|
Packit Service |
3a6627 |
//
|
|
Packit Service |
3a6627 |
// would return the correct path item.
|
|
Packit Service |
3a6627 |
func (paths Paths) Find(key string) *PathItem {
|
|
Packit Service |
3a6627 |
// Try directly access the map
|
|
Packit Service |
3a6627 |
pathItem := paths[key]
|
|
Packit Service |
3a6627 |
if pathItem != nil {
|
|
Packit Service |
3a6627 |
return pathItem
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
normalizedPath, expected := normalizeTemplatedPath(key)
|
|
Packit Service |
3a6627 |
for path, pathItem := range paths {
|
|
Packit Service |
3a6627 |
pathNormalized, got := normalizeTemplatedPath(path)
|
|
Packit Service |
3a6627 |
if got == expected && pathNormalized == normalizedPath {
|
|
Packit Service |
3a6627 |
return pathItem
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
return nil
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
func normalizeTemplatedPath(path string) (string, uint) {
|
|
Packit Service |
3a6627 |
if strings.IndexByte(path, '{') < 0 {
|
|
Packit Service |
3a6627 |
return path, 0
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
var buf strings.Builder
|
|
Packit Service |
3a6627 |
buf.Grow(len(path))
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
var (
|
|
Packit Service |
3a6627 |
cc rune
|
|
Packit Service |
3a6627 |
count uint
|
|
Packit Service |
3a6627 |
isVariable bool
|
|
Packit Service |
3a6627 |
)
|
|
Packit Service |
3a6627 |
for i, c := range path {
|
|
Packit Service |
3a6627 |
if isVariable {
|
|
Packit Service |
3a6627 |
if c == '}' {
|
|
Packit Service |
3a6627 |
// End path variables
|
|
Packit Service |
3a6627 |
// First append possible '*' before this character
|
|
Packit Service |
3a6627 |
// The character '}' will be appended
|
|
Packit Service |
3a6627 |
if i > 0 && cc == '*' {
|
|
Packit Service |
3a6627 |
buf.WriteRune(cc)
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
isVariable = false
|
|
Packit Service |
3a6627 |
} else {
|
|
Packit Service |
3a6627 |
// Skip this character
|
|
Packit Service |
3a6627 |
continue
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
} else if c == '{' {
|
|
Packit Service |
3a6627 |
// Begin path variable
|
|
Packit Service |
3a6627 |
// The character '{' will be appended
|
|
Packit Service |
3a6627 |
isVariable = true
|
|
Packit Service |
3a6627 |
count++
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
|
|
Packit Service |
3a6627 |
// Append the character
|
|
Packit Service |
3a6627 |
buf.WriteRune(c)
|
|
Packit Service |
3a6627 |
cc = c
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
return buf.String(), count
|
|
Packit Service |
3a6627 |
}
|