Update a few dependencies
github.com/go-openapi/* github.com/asaskevich/govalidator
This commit is contained in:
393
vendor/github.com/go-openapi/spec/expander.go
generated
vendored
393
vendor/github.com/go-openapi/spec/expander.go
generated
vendored
@@ -30,16 +30,12 @@ import (
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
var (
|
||||
// Debug enables logging when SWAGGER_DEBUG env var is not empty
|
||||
Debug = os.Getenv("SWAGGER_DEBUG") != ""
|
||||
)
|
||||
|
||||
// ExpandOptions provides options for expand.
|
||||
type ExpandOptions struct {
|
||||
RelativeBase string
|
||||
SkipSchemas bool
|
||||
ContinueOnError bool
|
||||
RelativeBase string
|
||||
SkipSchemas bool
|
||||
ContinueOnError bool
|
||||
AbsoluteCircularRef bool
|
||||
}
|
||||
|
||||
// ResolutionCache a cache for resolving urls
|
||||
@@ -49,7 +45,7 @@ type ResolutionCache interface {
|
||||
}
|
||||
|
||||
type simpleCache struct {
|
||||
lock sync.Mutex
|
||||
lock sync.RWMutex
|
||||
store map[string]interface{}
|
||||
}
|
||||
|
||||
@@ -59,6 +55,7 @@ func init() {
|
||||
resCache = initResolutionCache()
|
||||
}
|
||||
|
||||
// initResolutionCache initializes the URI resolution cache
|
||||
func initResolutionCache() ResolutionCache {
|
||||
return &simpleCache{store: map[string]interface{}{
|
||||
"http://swagger.io/v2/schema.json": MustLoadSwagger20Schema(),
|
||||
@@ -66,16 +63,37 @@ func initResolutionCache() ResolutionCache {
|
||||
}}
|
||||
}
|
||||
|
||||
// resolverContext allows to share a context during spec processing.
|
||||
// At the moment, it just holds the index of circular references found.
|
||||
type resolverContext struct {
|
||||
// circulars holds all visited circular references, which allows shortcuts.
|
||||
// NOTE: this is not just a performance improvement: it is required to figure out
|
||||
// circular references which participate several cycles.
|
||||
// This structure is privately instantiated and needs not be locked against
|
||||
// concurrent access, unless we chose to implement a parallel spec walking.
|
||||
circulars map[string]bool
|
||||
basePath string
|
||||
}
|
||||
|
||||
func newResolverContext(originalBasePath string) *resolverContext {
|
||||
return &resolverContext{
|
||||
circulars: make(map[string]bool),
|
||||
basePath: originalBasePath, // keep the root base path in context
|
||||
}
|
||||
}
|
||||
|
||||
// Get retrieves a cached URI
|
||||
func (s *simpleCache) Get(uri string) (interface{}, bool) {
|
||||
debugLog("getting %q from resolution cache", uri)
|
||||
s.lock.Lock()
|
||||
s.lock.RLock()
|
||||
v, ok := s.store[uri]
|
||||
debugLog("got %q from resolution cache: %t", uri, ok)
|
||||
|
||||
s.lock.Unlock()
|
||||
s.lock.RUnlock()
|
||||
return v, ok
|
||||
}
|
||||
|
||||
// Set caches a URI
|
||||
func (s *simpleCache) Set(uri string, data interface{}) {
|
||||
s.lock.Lock()
|
||||
s.store[uri] = data
|
||||
@@ -84,7 +102,7 @@ func (s *simpleCache) Set(uri string, data interface{}) {
|
||||
|
||||
// ResolveRefWithBase resolves a reference against a context root with preservation of base path
|
||||
func ResolveRefWithBase(root interface{}, ref *Ref, opts *ExpandOptions) (*Schema, error) {
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil)
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -116,21 +134,21 @@ func ResolveRef(root interface{}, ref *Ref) (*Schema, error) {
|
||||
case map[string]interface{}:
|
||||
b, _ := json.Marshal(sch)
|
||||
newSch := new(Schema)
|
||||
json.Unmarshal(b, newSch)
|
||||
_ = json.Unmarshal(b, newSch)
|
||||
return newSch, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown type for the resolved reference")
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveParameter resolves a paramter reference against a context root
|
||||
// ResolveParameter resolves a parameter reference against a context root
|
||||
func ResolveParameter(root interface{}, ref Ref) (*Parameter, error) {
|
||||
return ResolveParameterWithBase(root, ref, nil)
|
||||
}
|
||||
|
||||
// ResolveParameterWithBase resolves a paramter reference against a context root and base path
|
||||
// ResolveParameterWithBase resolves a parameter reference against a context root and base path
|
||||
func ResolveParameterWithBase(root interface{}, ref Ref, opts *ExpandOptions) (*Parameter, error) {
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil)
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -149,7 +167,7 @@ func ResolveResponse(root interface{}, ref Ref) (*Response, error) {
|
||||
|
||||
// ResolveResponseWithBase resolves response a reference against a context root and base path
|
||||
func ResolveResponseWithBase(root interface{}, ref Ref, opts *ExpandOptions) (*Response, error) {
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil)
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -163,7 +181,7 @@ func ResolveResponseWithBase(root interface{}, ref Ref, opts *ExpandOptions) (*R
|
||||
|
||||
// ResolveItems resolves header and parameter items reference against a context root and base path
|
||||
func ResolveItems(root interface{}, ref Ref, opts *ExpandOptions) (*Items, error) {
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil)
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -180,7 +198,7 @@ func ResolveItems(root interface{}, ref Ref, opts *ExpandOptions) (*Items, error
|
||||
|
||||
// ResolvePathItem resolves response a path item against a context root and base path
|
||||
func ResolvePathItem(root interface{}, ref Ref, opts *ExpandOptions) (*PathItem, error) {
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil)
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -199,6 +217,7 @@ type schemaLoader struct {
|
||||
root interface{}
|
||||
options *ExpandOptions
|
||||
cache ResolutionCache
|
||||
context *resolverContext
|
||||
loadDoc func(string) (json.RawMessage, error)
|
||||
}
|
||||
|
||||
@@ -221,7 +240,8 @@ func init() {
|
||||
func defaultSchemaLoader(
|
||||
root interface{},
|
||||
expandOptions *ExpandOptions,
|
||||
cache ResolutionCache) (*schemaLoader, error) {
|
||||
cache ResolutionCache,
|
||||
context *resolverContext) (*schemaLoader, error) {
|
||||
|
||||
if cache == nil {
|
||||
cache = resCache
|
||||
@@ -229,11 +249,15 @@ func defaultSchemaLoader(
|
||||
if expandOptions == nil {
|
||||
expandOptions = &ExpandOptions{}
|
||||
}
|
||||
|
||||
absBase, _ := absPath(expandOptions.RelativeBase)
|
||||
if context == nil {
|
||||
context = newResolverContext(absBase)
|
||||
}
|
||||
return &schemaLoader{
|
||||
root: root,
|
||||
options: expandOptions,
|
||||
cache: cache,
|
||||
context: context,
|
||||
loadDoc: func(path string) (json.RawMessage, error) {
|
||||
debugLog("fetching document at %q", path)
|
||||
return PathLoader(path)
|
||||
@@ -312,12 +336,6 @@ func nextRef(startingNode interface{}, startingRef *Ref, ptr *jsonpointer.Pointe
|
||||
return ret
|
||||
}
|
||||
|
||||
func debugLog(msg string, args ...interface{}) {
|
||||
if Debug {
|
||||
log.Printf(msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// normalize absolute path for cache.
|
||||
// on Windows, drive letters should be converted to lower as scheme in net/url.URL
|
||||
func normalizeAbsPath(path string) string {
|
||||
@@ -336,12 +354,17 @@ func normalizeAbsPath(path string) string {
|
||||
// base could be a directory or a full file path
|
||||
func normalizePaths(refPath, base string) string {
|
||||
refURL, _ := url.Parse(refPath)
|
||||
if path.IsAbs(refURL.Path) {
|
||||
if path.IsAbs(refURL.Path) || filepath.IsAbs(refPath) {
|
||||
// refPath is actually absolute
|
||||
if refURL.Host != "" {
|
||||
return refPath
|
||||
}
|
||||
return filepath.FromSlash(refPath)
|
||||
parts := strings.Split(refPath, "#")
|
||||
result := filepath.FromSlash(parts[0])
|
||||
if len(parts) == 2 {
|
||||
result += "#" + parts[1]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// relative refPath
|
||||
@@ -361,6 +384,59 @@ func normalizePaths(refPath, base string) string {
|
||||
return baseURL.String()
|
||||
}
|
||||
|
||||
// denormalizePaths returns to simplest notation on file $ref,
|
||||
// i.e. strips the absolute path and sets a path relative to the base path.
|
||||
//
|
||||
// This is currently used when we rewrite ref after a circular ref has been detected
|
||||
func denormalizeFileRef(ref *Ref, relativeBase, originalRelativeBase string) *Ref {
|
||||
debugLog("denormalizeFileRef for: %s", ref.String())
|
||||
|
||||
if ref.String() == "" || ref.IsRoot() || ref.HasFragmentOnly {
|
||||
return ref
|
||||
}
|
||||
// strip relativeBase from URI
|
||||
relativeBaseURL, _ := url.Parse(relativeBase)
|
||||
relativeBaseURL.Fragment = ""
|
||||
|
||||
if relativeBaseURL.IsAbs() && strings.HasPrefix(ref.String(), relativeBase) {
|
||||
// this should work for absolute URI (e.g. http://...): we have an exact match, just trim prefix
|
||||
r, _ := NewRef(strings.TrimPrefix(ref.String(), relativeBase))
|
||||
return &r
|
||||
}
|
||||
|
||||
if relativeBaseURL.IsAbs() {
|
||||
// other absolute URL get unchanged (i.e. with a non-empty scheme)
|
||||
return ref
|
||||
}
|
||||
|
||||
// for relative file URIs:
|
||||
originalRelativeBaseURL, _ := url.Parse(originalRelativeBase)
|
||||
originalRelativeBaseURL.Fragment = ""
|
||||
if strings.HasPrefix(ref.String(), originalRelativeBaseURL.String()) {
|
||||
// the resulting ref is in the expanded spec: return a local ref
|
||||
r, _ := NewRef(strings.TrimPrefix(ref.String(), originalRelativeBaseURL.String()))
|
||||
return &r
|
||||
}
|
||||
|
||||
// check if we may set a relative path, considering the original base path for this spec.
|
||||
// Example:
|
||||
// spec is located at /mypath/spec.json
|
||||
// my normalized ref points to: /mypath/item.json#/target
|
||||
// expected result: item.json#/target
|
||||
parts := strings.Split(ref.String(), "#")
|
||||
relativePath, err := filepath.Rel(path.Dir(originalRelativeBaseURL.String()), parts[0])
|
||||
if err != nil {
|
||||
// there is no common ancestor (e.g. different drives on windows)
|
||||
// leaves the ref unchanged
|
||||
return ref
|
||||
}
|
||||
if len(parts) == 2 {
|
||||
relativePath += "#" + parts[1]
|
||||
}
|
||||
r, _ := NewRef(relativePath)
|
||||
return &r
|
||||
}
|
||||
|
||||
// relativeBase could be an ABSOLUTE file path or an ABSOLUTE URL
|
||||
func normalizeFileRef(ref *Ref, relativeBase string) *Ref {
|
||||
// This is important for when the reference is pointing to the root schema
|
||||
@@ -369,8 +445,7 @@ func normalizeFileRef(ref *Ref, relativeBase string) *Ref {
|
||||
return &r
|
||||
}
|
||||
|
||||
refURL := ref.GetURL()
|
||||
debugLog("normalizing %s against %s (%s)", ref.String(), relativeBase, refURL.String())
|
||||
debugLog("normalizing %s against %s", ref.String(), relativeBase)
|
||||
|
||||
s := normalizePaths(ref.String(), relativeBase)
|
||||
r, _ := NewRef(s)
|
||||
@@ -395,7 +470,7 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string)
|
||||
// it is pointing somewhere in the root.
|
||||
root := r.root
|
||||
if (ref.IsRoot() || ref.HasFragmentOnly) && root == nil && basePath != "" {
|
||||
if baseRef, err := NewRef(basePath); err == nil {
|
||||
if baseRef, erb := NewRef(basePath); erb == nil {
|
||||
root, _, _, _ = r.load(baseRef.GetURL())
|
||||
}
|
||||
}
|
||||
@@ -430,9 +505,11 @@ func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error)
|
||||
toFetch := *refURL
|
||||
toFetch.Fragment = ""
|
||||
|
||||
data, fromCache := r.cache.Get(toFetch.String())
|
||||
normalized := normalizeAbsPath(toFetch.String())
|
||||
|
||||
data, fromCache := r.cache.Get(normalized)
|
||||
if !fromCache {
|
||||
b, err := r.loadDoc(toFetch.String())
|
||||
b, err := r.loadDoc(normalized)
|
||||
if err != nil {
|
||||
return nil, url.URL{}, false, err
|
||||
}
|
||||
@@ -440,7 +517,7 @@ func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error)
|
||||
if err := json.Unmarshal(b, &data); err != nil {
|
||||
return nil, url.URL{}, false, err
|
||||
}
|
||||
r.cache.Set(toFetch.String(), data)
|
||||
r.cache.Set(normalized, data)
|
||||
}
|
||||
|
||||
return data, toFetch, fromCache, nil
|
||||
@@ -468,7 +545,7 @@ func absPath(fname string) (string, error) {
|
||||
|
||||
// ExpandSpec expands the references in a swagger spec
|
||||
func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
|
||||
resolver, err := defaultSchemaLoader(spec, options, nil)
|
||||
resolver, err := defaultSchemaLoader(spec, options, nil, nil)
|
||||
// Just in case this ever returns an error.
|
||||
if shouldStopOnError(err, resolver.options) {
|
||||
return err
|
||||
@@ -484,7 +561,7 @@ func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
|
||||
for key, definition := range spec.Definitions {
|
||||
var def *Schema
|
||||
var err error
|
||||
if def, err = expandSchema(definition, []string{fmt.Sprintf("#/defintions/%s", key)}, resolver, specBasePath); shouldStopOnError(err, resolver.options) {
|
||||
if def, err = expandSchema(definition, []string{fmt.Sprintf("#/definitions/%s", key)}, resolver, specBasePath); shouldStopOnError(err, resolver.options) {
|
||||
return err
|
||||
}
|
||||
if def != nil {
|
||||
@@ -531,25 +608,35 @@ func shouldStopOnError(err error, opts *ExpandOptions) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ExpandSchema expands the refs in the schema object with reference to the root object
|
||||
// go-openapi/validate uses this function
|
||||
// notice that it is impossible to reference a json scema in a different file other than root
|
||||
func ExpandSchema(schema *Schema, root interface{}, cache ResolutionCache) error {
|
||||
// Only save the root to a tmp file if it isn't nil.
|
||||
var base string
|
||||
// baseForRoot loads in the cache the root document and produces a fake "root" base path entry
|
||||
// for further $ref resolution
|
||||
func baseForRoot(root interface{}, cache ResolutionCache) string {
|
||||
// cache the root document to resolve $ref's
|
||||
const rootBase = "root"
|
||||
if root != nil {
|
||||
base, _ = absPath("root")
|
||||
base, _ := absPath(rootBase)
|
||||
normalizedBase := normalizeAbsPath(base)
|
||||
debugLog("setting root doc in cache at: %s", normalizedBase)
|
||||
if cache == nil {
|
||||
cache = resCache
|
||||
}
|
||||
cache.Set(normalizeAbsPath(base), root)
|
||||
base = "root"
|
||||
cache.Set(normalizedBase, root)
|
||||
return rootBase
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ExpandSchema expands the refs in the schema object with reference to the root object
|
||||
// go-openapi/validate uses this function
|
||||
// notice that it is impossible to reference a json schema in a different file other than root
|
||||
func ExpandSchema(schema *Schema, root interface{}, cache ResolutionCache) error {
|
||||
opts := &ExpandOptions{
|
||||
RelativeBase: base,
|
||||
// when a root is specified, cache the root as an in-memory document for $ref retrieval
|
||||
RelativeBase: baseForRoot(root, cache),
|
||||
SkipSchemas: false,
|
||||
ContinueOnError: false,
|
||||
// when no base path is specified, remaining $ref (circular) are rendered with an absolute path
|
||||
AbsoluteCircularRef: true,
|
||||
}
|
||||
return ExpandSchemaWithBasePath(schema, cache, opts)
|
||||
}
|
||||
@@ -565,7 +652,7 @@ func ExpandSchemaWithBasePath(schema *Schema, cache ResolutionCache, opts *Expan
|
||||
basePath, _ = absPath(opts.RelativeBase)
|
||||
}
|
||||
|
||||
resolver, err := defaultSchemaLoader(nil, opts, cache)
|
||||
resolver, err := defaultSchemaLoader(nil, opts, cache, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -617,8 +704,32 @@ func basePathFromSchemaID(oldBasePath, id string) string {
|
||||
return u.String()
|
||||
}
|
||||
|
||||
func isCircular(ref *Ref, basePath string, parentRefs ...string) bool {
|
||||
return basePath != "" && swag.ContainsStringsCI(parentRefs, ref.String())
|
||||
// isCircular detects cycles in sequences of $ref.
|
||||
// It relies on a private context (which needs not be locked).
|
||||
func (r *schemaLoader) isCircular(ref *Ref, basePath string, parentRefs ...string) (foundCycle bool) {
|
||||
normalizedRef := normalizePaths(ref.String(), basePath)
|
||||
if _, ok := r.context.circulars[normalizedRef]; ok {
|
||||
// circular $ref has been already detected in another explored cycle
|
||||
foundCycle = true
|
||||
return
|
||||
}
|
||||
foundCycle = swag.ContainsStringsCI(parentRefs, normalizedRef)
|
||||
if foundCycle {
|
||||
r.context.circulars[normalizedRef] = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func updateBasePath(transitive *schemaLoader, resolver *schemaLoader, basePath string) string {
|
||||
if transitive != resolver {
|
||||
debugLog("got a new resolver")
|
||||
if transitive.options != nil && transitive.options.RelativeBase != "" {
|
||||
basePath, _ = absPath(transitive.options.RelativeBase)
|
||||
debugLog("new basePath = %s", basePath)
|
||||
}
|
||||
}
|
||||
|
||||
return basePath
|
||||
}
|
||||
|
||||
func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) {
|
||||
@@ -634,6 +745,7 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
|
||||
otherwise the basePath should inherit the parent's */
|
||||
// important: ID can be relative path
|
||||
if target.ID != "" {
|
||||
debugLog("schema has ID: %s", target.ID)
|
||||
// handling the case when id is a folder
|
||||
// remember that basePath has to be a file
|
||||
refPath := target.ID
|
||||
@@ -645,7 +757,6 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
|
||||
}
|
||||
|
||||
/* Explain here what this function does */
|
||||
|
||||
var t *Schema
|
||||
/* if Ref is found, everything else doesn't matter */
|
||||
/* Ref also changes the resolution scope of children expandSchema */
|
||||
@@ -654,14 +765,21 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
|
||||
normalizedRef := normalizeFileRef(&target.Ref, basePath)
|
||||
normalizedBasePath := normalizedRef.RemoteURI()
|
||||
|
||||
/* this means there is a circle in the recursion tree */
|
||||
/* return the Ref */
|
||||
if isCircular(normalizedRef, basePath, parentRefs...) {
|
||||
target.Ref = *normalizedRef
|
||||
if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
|
||||
// this means there is a cycle in the recursion tree: return the Ref
|
||||
// - circular refs cannot be expanded. We leave them as ref.
|
||||
// - denormalization means that a new local file ref is set relative to the original basePath
|
||||
debugLog("shortcut circular ref: basePath: %s, normalizedPath: %s, normalized ref: %s",
|
||||
basePath, normalizedBasePath, normalizedRef.String())
|
||||
if !resolver.options.AbsoluteCircularRef {
|
||||
target.Ref = *denormalizeFileRef(normalizedRef, normalizedBasePath, resolver.context.basePath)
|
||||
} else {
|
||||
target.Ref = *normalizedRef
|
||||
}
|
||||
return &target, nil
|
||||
}
|
||||
|
||||
debugLog("\nbasePath: %s", basePath)
|
||||
debugLog("basePath: %s", basePath)
|
||||
if Debug {
|
||||
b, _ := json.Marshal(target)
|
||||
debugLog("calling Resolve with target: %s", string(b))
|
||||
@@ -672,7 +790,15 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
|
||||
|
||||
if t != nil {
|
||||
parentRefs = append(parentRefs, normalizedRef.String())
|
||||
return expandSchema(*t, parentRefs, resolver, normalizedBasePath)
|
||||
var err error
|
||||
transitiveResolver, err := transitiveResolver(basePath, target.Ref, resolver)
|
||||
if shouldStopOnError(err, resolver.options) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
basePath = updateBasePath(transitiveResolver, resolver, normalizedBasePath)
|
||||
|
||||
return expandSchema(*t, parentRefs, transitiveResolver, basePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,7 +907,7 @@ func derefPathItem(pathItem *PathItem, parentRefs []string, resolver *schemaLoad
|
||||
normalizedRef := normalizeFileRef(&pathItem.Ref, basePath)
|
||||
normalizedBasePath := normalizedRef.RemoteURI()
|
||||
|
||||
if isCircular(normalizedRef, basePath, parentRefs...) {
|
||||
if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -807,9 +933,17 @@ func expandPathItem(pathItem *PathItem, resolver *schemaLoader, basePath string)
|
||||
if err := derefPathItem(pathItem, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
|
||||
return err
|
||||
}
|
||||
if pathItem.Ref.String() != "" {
|
||||
var err error
|
||||
resolver, err = transitiveResolver(basePath, pathItem.Ref, resolver)
|
||||
if shouldStopOnError(err, resolver.options) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
pathItem.Ref = Ref{}
|
||||
|
||||
parentRefs = parentRefs[0:]
|
||||
// Currently unused:
|
||||
//parentRefs = parentRefs[0:]
|
||||
|
||||
for idx := range pathItem.Parameters {
|
||||
if err := expandParameter(&(pathItem.Parameters[idx]), resolver, basePath); shouldStopOnError(err, resolver.options) {
|
||||
@@ -867,19 +1001,68 @@ func expandOperation(op *Operation, resolver *schemaLoader, basePath string) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExpandResponse expands a response based on a basepath
|
||||
// This is the exported version of expandResponse
|
||||
// all refs inside response will be resolved relative to basePath
|
||||
func ExpandResponse(response *Response, basePath string) error {
|
||||
opts := &ExpandOptions{
|
||||
RelativeBase: basePath,
|
||||
func transitiveResolver(basePath string, ref Ref, resolver *schemaLoader) (*schemaLoader, error) {
|
||||
if ref.IsRoot() || ref.HasFragmentOnly {
|
||||
return resolver, nil
|
||||
}
|
||||
resolver, err := defaultSchemaLoader(nil, opts, nil)
|
||||
|
||||
baseRef, _ := NewRef(basePath)
|
||||
currentRef := normalizeFileRef(&ref, basePath)
|
||||
// Set a new root to resolve against
|
||||
if !strings.HasPrefix(currentRef.String(), baseRef.String()) {
|
||||
rootURL := currentRef.GetURL()
|
||||
rootURL.Fragment = ""
|
||||
root, _ := resolver.cache.Get(rootURL.String())
|
||||
var err error
|
||||
|
||||
// shallow copy of resolver options to set a new RelativeBase when
|
||||
// traversing multiple documents
|
||||
newOptions := resolver.options
|
||||
newOptions.RelativeBase = rootURL.String()
|
||||
debugLog("setting new root: %s", newOptions.RelativeBase)
|
||||
resolver, err = defaultSchemaLoader(root, newOptions, resolver.cache, resolver.context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return resolver, nil
|
||||
}
|
||||
|
||||
// ExpandResponseWithRoot expands a response based on a root document, not a fetchable document
|
||||
func ExpandResponseWithRoot(response *Response, root interface{}, cache ResolutionCache) error {
|
||||
opts := &ExpandOptions{
|
||||
RelativeBase: baseForRoot(root, cache),
|
||||
SkipSchemas: false,
|
||||
ContinueOnError: false,
|
||||
// when no base path is specified, remaining $ref (circular) are rendered with an absolute path
|
||||
AbsoluteCircularRef: true,
|
||||
}
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expandResponse(response, resolver, basePath)
|
||||
return expandResponse(response, resolver, opts.RelativeBase)
|
||||
}
|
||||
|
||||
// ExpandResponse expands a response based on a basepath
|
||||
// This is the exported version of expandResponse
|
||||
// all refs inside response will be resolved relative to basePath
|
||||
func ExpandResponse(response *Response, basePath string) error {
|
||||
var specBasePath string
|
||||
if basePath != "" {
|
||||
specBasePath, _ = absPath(basePath)
|
||||
}
|
||||
opts := &ExpandOptions{
|
||||
RelativeBase: specBasePath,
|
||||
}
|
||||
resolver, err := defaultSchemaLoader(nil, opts, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expandResponse(response, resolver, opts.RelativeBase)
|
||||
}
|
||||
|
||||
func derefResponse(response *Response, parentRefs []string, resolver *schemaLoader, basePath string) error {
|
||||
@@ -889,7 +1072,7 @@ func derefResponse(response *Response, parentRefs []string, resolver *schemaLoad
|
||||
normalizedRef := normalizeFileRef(&response.Ref, basePath)
|
||||
normalizedBasePath := normalizedRef.RemoteURI()
|
||||
|
||||
if isCircular(normalizedRef, basePath, parentRefs...) {
|
||||
if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -910,16 +1093,31 @@ func expandResponse(response *Response, resolver *schemaLoader, basePath string)
|
||||
if response == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
parentRefs := []string{}
|
||||
if err := derefResponse(response, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
|
||||
return err
|
||||
}
|
||||
if response.Ref.String() != "" {
|
||||
transitiveResolver, err := transitiveResolver(basePath, response.Ref, resolver)
|
||||
if shouldStopOnError(err, transitiveResolver.options) {
|
||||
return err
|
||||
}
|
||||
basePath = updateBasePath(transitiveResolver, resolver, basePath)
|
||||
resolver = transitiveResolver
|
||||
}
|
||||
if response.Schema != nil && response.Schema.Ref.String() != "" {
|
||||
// schema expanded to a $ref in another root
|
||||
var ern error
|
||||
response.Schema.Ref, ern = NewRef(normalizePaths(response.Schema.Ref.String(), response.Ref.RemoteURI()))
|
||||
if ern != nil {
|
||||
return ern
|
||||
}
|
||||
}
|
||||
response.Ref = Ref{}
|
||||
|
||||
parentRefs = parentRefs[0:]
|
||||
if !resolver.options.SkipSchemas && response.Schema != nil {
|
||||
parentRefs = append(parentRefs, response.Schema.Ref.String())
|
||||
// parentRefs = append(parentRefs, response.Schema.Ref.String())
|
||||
s, err := expandSchema(*response.Schema, parentRefs, resolver, basePath)
|
||||
if shouldStopOnError(err, resolver.options) {
|
||||
return err
|
||||
@@ -930,19 +1128,40 @@ func expandResponse(response *Response, resolver *schemaLoader, basePath string)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExpandParameter expands a parameter based on a basepath
|
||||
// This is the exported version of expandParameter
|
||||
// all refs inside parameter will be resolved relative to basePath
|
||||
func ExpandParameter(parameter *Parameter, basePath string) error {
|
||||
// ExpandParameterWithRoot expands a parameter based on a root document, not a fetchable document
|
||||
func ExpandParameterWithRoot(parameter *Parameter, root interface{}, cache ResolutionCache) error {
|
||||
opts := &ExpandOptions{
|
||||
RelativeBase: basePath,
|
||||
RelativeBase: baseForRoot(root, cache),
|
||||
SkipSchemas: false,
|
||||
ContinueOnError: false,
|
||||
// when no base path is specified, remaining $ref (circular) are rendered with an absolute path
|
||||
AbsoluteCircularRef: true,
|
||||
}
|
||||
resolver, err := defaultSchemaLoader(nil, opts, nil)
|
||||
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expandParameter(parameter, resolver, basePath)
|
||||
return expandParameter(parameter, resolver, opts.RelativeBase)
|
||||
}
|
||||
|
||||
// ExpandParameter expands a parameter based on a basepath
|
||||
// This is the exported version of expandParameter
|
||||
// all refs inside parameter will be resolved relative to basePath
|
||||
func ExpandParameter(parameter *Parameter, basePath string) error {
|
||||
var specBasePath string
|
||||
if basePath != "" {
|
||||
specBasePath, _ = absPath(basePath)
|
||||
}
|
||||
opts := &ExpandOptions{
|
||||
RelativeBase: specBasePath,
|
||||
}
|
||||
resolver, err := defaultSchemaLoader(nil, opts, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expandParameter(parameter, resolver, opts.RelativeBase)
|
||||
}
|
||||
|
||||
func derefParameter(parameter *Parameter, parentRefs []string, resolver *schemaLoader, basePath string) error {
|
||||
@@ -951,7 +1170,7 @@ func derefParameter(parameter *Parameter, parentRefs []string, resolver *schemaL
|
||||
normalizedRef := normalizeFileRef(¶meter.Ref, basePath)
|
||||
normalizedBasePath := normalizedRef.RemoteURI()
|
||||
|
||||
if isCircular(normalizedRef, basePath, parentRefs...) {
|
||||
if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -977,11 +1196,27 @@ func expandParameter(parameter *Parameter, resolver *schemaLoader, basePath stri
|
||||
if err := derefParameter(parameter, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
|
||||
return err
|
||||
}
|
||||
if parameter.Ref.String() != "" {
|
||||
transitiveResolver, err := transitiveResolver(basePath, parameter.Ref, resolver)
|
||||
if shouldStopOnError(err, transitiveResolver.options) {
|
||||
return err
|
||||
}
|
||||
basePath = updateBasePath(transitiveResolver, resolver, basePath)
|
||||
resolver = transitiveResolver
|
||||
}
|
||||
|
||||
if parameter.Schema != nil && parameter.Schema.Ref.String() != "" {
|
||||
// schema expanded to a $ref in another root
|
||||
var ern error
|
||||
parameter.Schema.Ref, ern = NewRef(normalizePaths(parameter.Schema.Ref.String(), parameter.Ref.RemoteURI()))
|
||||
if ern != nil {
|
||||
return ern
|
||||
}
|
||||
}
|
||||
parameter.Ref = Ref{}
|
||||
|
||||
parentRefs = parentRefs[0:]
|
||||
if !resolver.options.SkipSchemas && parameter.Schema != nil {
|
||||
parentRefs = append(parentRefs, parameter.Schema.Ref.String())
|
||||
s, err := expandSchema(*parameter.Schema, parentRefs, resolver, basePath)
|
||||
if shouldStopOnError(err, resolver.options) {
|
||||
return err
|
||||
|
Reference in New Issue
Block a user