Blame vendor/github.com/getkin/kin-openapi/openapi3/paths.go

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
}