aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-openapi/spec/schema_loader.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-openapi/spec/schema_loader.go')
-rw-r--r--vendor/github.com/go-openapi/spec/schema_loader.go94
1 files changed, 53 insertions, 41 deletions
diff --git a/vendor/github.com/go-openapi/spec/schema_loader.go b/vendor/github.com/go-openapi/spec/schema_loader.go
index 9ea78b5d52..0059b99aed 100644
--- a/vendor/github.com/go-openapi/spec/schema_loader.go
+++ b/vendor/github.com/go-openapi/spec/schema_loader.go
@@ -33,16 +33,12 @@ import (
// NOTE: if you are using the go-openapi/loads package, it will override
// this value with its own default (a loader to retrieve YAML documents as
// well as JSON ones).
-var PathLoader func(string) (json.RawMessage, error)
-
-func init() {
- PathLoader = func(path string) (json.RawMessage, error) {
- data, err := swag.LoadFromFileOrHTTP(path)
- if err != nil {
- return nil, err
- }
- return json.RawMessage(data), nil
+var PathLoader = func(pth string) (json.RawMessage, error) {
+ data, err := swag.LoadFromFileOrHTTP(pth)
+ if err != nil {
+ return nil, err
}
+ return json.RawMessage(data), nil
}
// resolverContext allows to share a context during spec processing.
@@ -55,12 +51,13 @@ type resolverContext struct {
circulars map[string]bool
basePath string
loadDoc func(string) (json.RawMessage, error)
+ rootID string
}
-func newResolverContext(expandOptions *ExpandOptions) *resolverContext {
- absBase, _ := absPath(expandOptions.RelativeBase)
+func newResolverContext(options *ExpandOptions) *resolverContext {
+ expandOptions := optionsOrDefault(options)
- // path loader may be overridden from option
+ // path loader may be overridden by options
var loader func(string) (json.RawMessage, error)
if expandOptions.PathLoader == nil {
loader = PathLoader
@@ -70,7 +67,7 @@ func newResolverContext(expandOptions *ExpandOptions) *resolverContext {
return &resolverContext{
circulars: make(map[string]bool),
- basePath: absBase, // keep the root base path in context
+ basePath: expandOptions.RelativeBase, // keep the root base path in context
loadDoc: loader,
}
}
@@ -88,7 +85,7 @@ func (r *schemaLoader) transitiveResolver(basePath string, ref Ref) *schemaLoade
}
baseRef := MustCreateRef(basePath)
- currentRef := normalizeFileRef(&ref, basePath)
+ currentRef := normalizeRef(&ref, basePath)
if strings.HasPrefix(currentRef.String(), baseRef.String()) {
return r
}
@@ -102,15 +99,17 @@ func (r *schemaLoader) transitiveResolver(basePath string, ref Ref) *schemaLoade
// traversing multiple documents
newOptions := r.options
newOptions.RelativeBase = rootURL.String()
+
return defaultSchemaLoader(root, newOptions, r.cache, r.context)
}
func (r *schemaLoader) updateBasePath(transitive *schemaLoader, basePath string) string {
if transitive != r {
if transitive.options != nil && transitive.options.RelativeBase != "" {
- basePath, _ = absPath(transitive.options.RelativeBase)
+ return normalizeBase(transitive.options.RelativeBase)
}
}
+
return basePath
}
@@ -142,7 +141,7 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string)
if (ref.IsRoot() || ref.HasFragmentOnly) && root != nil {
data = root
} else {
- baseRef := normalizeFileRef(ref, basePath)
+ baseRef := normalizeRef(ref, basePath)
data, _, _, err = r.load(baseRef.GetURL())
if err != nil {
return err
@@ -166,43 +165,39 @@ func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error)
var err error
pth := toFetch.String()
- if pth == rootBase {
- pth, err = absPath(rootBase)
- if err != nil {
- return nil, url.URL{}, false, err
- }
- }
- normalized := normalizeAbsPath(pth)
+ normalized := normalizeBase(pth)
+ debugLog("loading doc from: %s", normalized)
data, fromCache := r.cache.Get(normalized)
- if !fromCache {
- b, err := r.context.loadDoc(normalized)
- if err != nil {
- return nil, url.URL{}, false, fmt.Errorf("%s [%s]: %w", pth, normalized, err)
- }
+ if fromCache {
+ return data, toFetch, fromCache, nil
+ }
- var doc interface{}
- if err := json.Unmarshal(b, &doc); err != nil {
- return nil, url.URL{}, false, err
- }
- r.cache.Set(normalized, doc)
+ b, err := r.context.loadDoc(normalized)
+ if err != nil {
+ return nil, url.URL{}, false, err
+ }
- return doc, toFetch, fromCache, nil
+ var doc interface{}
+ if err := json.Unmarshal(b, &doc); err != nil {
+ return nil, url.URL{}, false, err
}
+ r.cache.Set(normalized, doc)
- return data, toFetch, fromCache, nil
+ return doc, toFetch, fromCache, nil
}
// 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)
+ normalizedRef := normalizeURI(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) // TODO(fred): normalize windows url and remove CI equality
+ foundCycle = swag.ContainsStrings(parentRefs, normalizedRef) // normalized windows url's are lower cased
if foundCycle {
r.context.circulars[normalizedRef] = true
}
@@ -240,7 +235,7 @@ func (r *schemaLoader) deref(input interface{}, parentRefs []string, basePath st
return nil
}
- normalizedRef := normalizeFileRef(ref, basePath)
+ normalizedRef := normalizeRef(ref, basePath)
normalizedBasePath := normalizedRef.RemoteURI()
if r.isCircular(normalizedRef, basePath, parentRefs...) {
@@ -279,7 +274,7 @@ func (r *schemaLoader) setSchemaID(target interface{}, id, basePath string) (str
// remember that basePath has to point to a file
var refPath string
if strings.HasSuffix(id, "/") {
- // path.Clean here would not work correctly if there is a scheme (e.g. https://...)
+ // ensure this is detected as a file, not a folder
refPath = fmt.Sprintf("%s%s", id, "placeholder.json")
} else {
refPath = id
@@ -288,11 +283,18 @@ func (r *schemaLoader) setSchemaID(target interface{}, id, basePath string) (str
// updates the current base path
// * important: ID can be a relative path
// * registers target to be fetchable from the new base proposed by this id
- newBasePath := normalizePaths(refPath, basePath)
+ newBasePath := normalizeURI(refPath, basePath)
// store found IDs for possible future reuse in $ref
r.cache.Set(newBasePath, target)
+ // the root document has an ID: all $ref relative to that ID may
+ // be rebased relative to the root document
+ if basePath == r.context.basePath {
+ debugLog("root document is a schema with ID: %s (normalized as:%s)", id, newBasePath)
+ r.context.rootID = newBasePath
+ }
+
return newBasePath, refPath
}
@@ -306,6 +308,16 @@ func defaultSchemaLoader(
expandOptions = &ExpandOptions{}
}
+ cache = cacheOrDefault(cache)
+
+ if expandOptions.RelativeBase == "" {
+ // if no relative base is provided, assume the root document
+ // contains all $ref, or at least, that the relative documents
+ // may be resolved from the current working directory.
+ expandOptions.RelativeBase = baseForRoot(root, cache)
+ }
+ debugLog("effective expander options: %#v", expandOptions)
+
if context == nil {
context = newResolverContext(expandOptions)
}
@@ -313,7 +325,7 @@ func defaultSchemaLoader(
return &schemaLoader{
root: root,
options: expandOptions,
- cache: cacheOrDefault(cache),
+ cache: cache,
context: context,
}
}