aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/go-openapi/spec/expander.go
diff options
context:
space:
mode:
authorGravatar Yong Tang <yong.tang.github@outlook.com> 2018-02-23 12:10:34 -0800
committerGravatar Miek Gieben <miek@miek.nl> 2018-02-23 20:10:34 +0000
commit604c0045e75e606e4bab9f1d57b3ba4eb75a2c31 (patch)
tree86213e326c230811bead2f7a79531f8f3eb5d795 /vendor/github.com/go-openapi/spec/expander.go
parent9047bdf3a096907c47ee1d3787a63fde85a13b6e (diff)
downloadcoredns-604c0045e75e606e4bab9f1d57b3ba4eb75a2c31.tar.gz
coredns-604c0045e75e606e4bab9f1d57b3ba4eb75a2c31.tar.zst
coredns-604c0045e75e606e4bab9f1d57b3ba4eb75a2c31.zip
Update go dep (#1560)
This fix updates go dep with `dep ensure --update` as well as the following: - Removed github.com/ugorji/go restriction in Gopkg.toml (fixes #1557) - Added github.com/flynn/go-shlex in Makefile (neede by Caddy, maybe removed later) This fix fixes #1557 Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Diffstat (limited to 'vendor/github.com/go-openapi/spec/expander.go')
-rw-r--r--vendor/github.com/go-openapi/spec/expander.go255
1 files changed, 173 insertions, 82 deletions
diff --git a/vendor/github.com/go-openapi/spec/expander.go b/vendor/github.com/go-openapi/spec/expander.go
index 59a227059..5054a7be6 100644
--- a/vendor/github.com/go-openapi/spec/expander.go
+++ b/vendor/github.com/go-openapi/spec/expander.go
@@ -16,9 +16,7 @@ package spec
import (
"encoding/json"
- "errors"
"fmt"
- "io/ioutil"
"log"
"net/url"
"os"
@@ -320,6 +318,17 @@ func debugLog(msg string, args ...interface{}) {
}
}
+// 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 {
+ u, err := url.Parse(path)
+ if err != nil {
+ debugLog("normalize absolute path failed: %s", err)
+ return path
+ }
+ return u.String()
+}
+
// base or refPath could be a file path or a URL
// given a base absolute path and a ref path, return the absolute path of refPath
// 1) if refPath is absolute, return it
@@ -379,32 +388,29 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string)
return nil
}
- // if no basePath is provided, we attempt to resolve the reference against root
- if basePath == "" {
- var b []byte
- switch rr := r.root.(type) {
- case *Schema:
- b, _ = rr.MarshalJSON()
- case *Swagger:
- b, _ = rr.MarshalJSON()
- }
- f, err := ioutil.TempFile(os.TempDir(), "tmproot")
+ var res interface{}
+ var data interface{}
+ var err error
+ // Resolve against the root if it isn't nil, and if ref is pointing at the root, or has a fragment only which means
+ // 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 {
+ root, _, _, _ = r.load(baseRef.GetURL())
+ }
+ }
+ if (ref.IsRoot() || ref.HasFragmentOnly) && root != nil {
+ data = root
+ } else {
+ baseRef := normalizeFileRef(ref, basePath)
+ debugLog("current ref is: %s", ref.String())
+ debugLog("current ref normalized file: %s", baseRef.String())
+ data, _, _, err = r.load(baseRef.GetURL())
if err != nil {
return err
}
- f.Write(b)
- f.Close()
- basePath = f.Name()
}
- baseRef := normalizeFileRef(ref, basePath)
- debugLog("current ref normalized file: %s", baseRef.String())
- data, _, _, err := r.load(baseRef.GetURL())
- if err != nil {
- return err
- }
-
- var res interface{}
res = data
if ref.String() != "" {
res, _, err = ref.GetPointer().Get(data)
@@ -415,6 +421,7 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string)
if err := swag.DynamicJSONToStruct(res, target); err != nil {
return err
}
+
return nil
}
@@ -449,6 +456,9 @@ func (r *schemaLoader) Resolve(ref *Ref, target interface{}, basePath string) er
// absPath returns the absolute path of a file
func absPath(fname string) (string, error) {
+ if strings.HasPrefix(fname, "http") {
+ return fname, nil
+ }
if filepath.IsAbs(fname) {
return fname, nil
}
@@ -471,11 +481,10 @@ func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
}
if options == nil || !options.SkipSchemas {
- rt := fmt.Sprintf("%s#/definitions/", specBasePath)
for key, definition := range spec.Definitions {
var def *Schema
var err error
- if def, err = expandSchema(definition, []string{rt + key}, resolver, specBasePath); shouldStopOnError(err, resolver.options) {
+ if def, err = expandSchema(definition, []string{fmt.Sprintf("#/defintions/%s", key)}, resolver, specBasePath); shouldStopOnError(err, resolver.options) {
return err
}
if def != nil {
@@ -526,29 +535,19 @@ func shouldStopOnError(err error, opts *ExpandOptions) bool {
// 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 {
- // if root is passed as nil, assume root is the same as schema
- if root == nil {
- root = schema
- }
-
- file, err := ioutil.TempFile(os.TempDir(), "root")
- if err != nil {
- return err
- }
- defer os.Remove(file.Name())
-
- switch r := root.(type) {
- case *Schema:
- b, _ := r.MarshalJSON()
- file.Write(b)
- case *Swagger:
- b, _ := r.MarshalJSON()
- file.Write(b)
+ // Only save the root to a tmp file if it isn't nil.
+ var base string
+ if root != nil {
+ base, _ = absPath("root")
+ if cache == nil {
+ cache = resCache
+ }
+ cache.Set(normalizeAbsPath(base), root)
+ base = "root"
}
- file.Close()
opts := &ExpandOptions{
- RelativeBase: file.Name(),
+ RelativeBase: base,
SkipSchemas: false,
ContinueOnError: false,
}
@@ -561,15 +560,11 @@ func ExpandSchemaWithBasePath(schema *Schema, cache ResolutionCache, opts *Expan
return nil
}
- if opts == nil {
- return errors.New("cannot expand schema without a base path")
- }
- if opts.RelativeBase == "" {
- return errors.New("cannot expand schema with empty base path")
+ var basePath string
+ if opts.RelativeBase != "" {
+ basePath, _ = absPath(opts.RelativeBase)
}
- basePath, _ := absPath(opts.RelativeBase)
-
resolver, err := defaultSchemaLoader(nil, opts, cache)
if err != nil {
return err
@@ -622,6 +617,10 @@ 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())
+}
+
func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) {
if target.Ref.String() == "" && target.Ref.IsRoot() {
// normalizing is important
@@ -657,14 +656,16 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
/* this means there is a circle in the recursion tree */
/* return the Ref */
- if basePath != "" && swag.ContainsStringsCI(parentRefs, normalizedRef.String()) {
+ if isCircular(normalizedRef, basePath, parentRefs...) {
target.Ref = *normalizedRef
return &target, nil
}
debugLog("\nbasePath: %s", basePath)
- b, _ := json.Marshal(target)
- debugLog("calling Resolve with target: %s", string(b))
+ if Debug {
+ b, _ := json.Marshal(target)
+ debugLog("calling Resolve with target: %s", string(b))
+ }
if err := resolver.Resolve(&target.Ref, &t, basePath); shouldStopOnError(err, resolver.options) {
return nil, err
}
@@ -774,17 +775,41 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
return &target, nil
}
+func derefPathItem(pathItem *PathItem, parentRefs []string, resolver *schemaLoader, basePath string) error {
+ curRef := pathItem.Ref.String()
+ if curRef != "" {
+ normalizedRef := normalizeFileRef(&pathItem.Ref, basePath)
+ normalizedBasePath := normalizedRef.RemoteURI()
+
+ if isCircular(normalizedRef, basePath, parentRefs...) {
+ return nil
+ }
+
+ if err := resolver.Resolve(&pathItem.Ref, pathItem, basePath); shouldStopOnError(err, resolver.options) {
+ return err
+ }
+
+ if pathItem.Ref.String() != "" && pathItem.Ref.String() != curRef && basePath != normalizedBasePath {
+ parentRefs = append(parentRefs, normalizedRef.String())
+ return derefPathItem(pathItem, parentRefs, resolver, normalizedBasePath)
+ }
+ }
+
+ return nil
+}
+
func expandPathItem(pathItem *PathItem, resolver *schemaLoader, basePath string) error {
if pathItem == nil {
return nil
}
- if pathItem.Ref.String() != "" {
- if err := resolver.Resolve(&pathItem.Ref, &pathItem, basePath); err != nil {
- return err
- }
- pathItem.Ref = Ref{}
+ parentRefs := []string{}
+ if err := derefPathItem(pathItem, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
+ return err
}
+ pathItem.Ref = Ref{}
+
+ parentRefs = parentRefs[0:]
for idx := range pathItem.Parameters {
if err := expandParameter(&(pathItem.Parameters[idx]), resolver, basePath); shouldStopOnError(err, resolver.options) {
@@ -842,53 +867,119 @@ 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,
+ }
+ resolver, err := defaultSchemaLoader(nil, opts, nil)
+ if err != nil {
+ return err
+ }
+
+ return expandResponse(response, resolver, basePath)
+}
+
+func derefResponse(response *Response, parentRefs []string, resolver *schemaLoader, basePath string) error {
+ curRef := response.Ref.String()
+ if curRef != "" {
+ /* Here the resolution scope is changed because a $ref was encountered */
+ normalizedRef := normalizeFileRef(&response.Ref, basePath)
+ normalizedBasePath := normalizedRef.RemoteURI()
+
+ if isCircular(normalizedRef, basePath, parentRefs...) {
+ return nil
+ }
+
+ if err := resolver.Resolve(&response.Ref, response, basePath); shouldStopOnError(err, resolver.options) {
+ return err
+ }
+
+ if response.Ref.String() != "" && response.Ref.String() != curRef && basePath != normalizedBasePath {
+ parentRefs = append(parentRefs, normalizedRef.String())
+ return derefResponse(response, parentRefs, resolver, normalizedBasePath)
+ }
+ }
+
+ return nil
+}
+
func expandResponse(response *Response, resolver *schemaLoader, basePath string) error {
if response == nil {
return nil
}
- var parentRefs []string
-
- if response.Ref.String() != "" {
- parentRefs = append(parentRefs, response.Ref.String())
- sch := new(Schema)
- b, _ := response.MarshalJSON()
- json.Unmarshal(b, sch)
- s, _ := expandSchema(*sch, parentRefs, resolver, basePath)
- // if err := resolver.Resolve(&response.Ref, response, basePath); shouldStopOnError(err, resolver.options) {
- // return err
- // }
- b, _ = s.MarshalJSON()
- json.Unmarshal(b, response)
- response.Ref = Ref{}
+ parentRefs := []string{}
+ if err := derefResponse(response, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
+ return err
}
+ response.Ref = Ref{}
+ parentRefs = parentRefs[0:]
if !resolver.options.SkipSchemas && response.Schema != nil {
parentRefs = append(parentRefs, response.Schema.Ref.String())
- debugLog("response ref: %s", response.Schema.Ref)
s, err := expandSchema(*response.Schema, parentRefs, resolver, basePath)
if shouldStopOnError(err, resolver.options) {
return err
}
*response.Schema = *s
}
+
return nil
}
-func expandParameter(parameter *Parameter, resolver *schemaLoader, basePath string) error {
- if parameter == nil {
- 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 {
+ opts := &ExpandOptions{
+ RelativeBase: basePath,
+ }
+ resolver, err := defaultSchemaLoader(nil, opts, nil)
+ if err != nil {
+ return err
}
- var parentRefs []string
+ return expandParameter(parameter, resolver, basePath)
+}
+
+func derefParameter(parameter *Parameter, parentRefs []string, resolver *schemaLoader, basePath string) error {
+ curRef := parameter.Ref.String()
+ if curRef != "" {
+ normalizedRef := normalizeFileRef(&parameter.Ref, basePath)
+ normalizedBasePath := normalizedRef.RemoteURI()
+
+ if isCircular(normalizedRef, basePath, parentRefs...) {
+ return nil
+ }
- if parameter.Ref.String() != "" {
- parentRefs = append(parentRefs, parameter.Ref.String())
if err := resolver.Resolve(&parameter.Ref, parameter, basePath); shouldStopOnError(err, resolver.options) {
return err
}
- parameter.Ref = Ref{}
+
+ if parameter.Ref.String() != "" && parameter.Ref.String() != curRef && basePath != normalizedBasePath {
+ parentRefs = append(parentRefs, normalizedRef.String())
+ return derefParameter(parameter, parentRefs, resolver, normalizedBasePath)
+ }
}
+
+ return nil
+}
+
+func expandParameter(parameter *Parameter, resolver *schemaLoader, basePath string) error {
+ if parameter == nil {
+ return nil
+ }
+
+ parentRefs := []string{}
+ if err := derefParameter(parameter, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
+ return err
+ }
+ 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)