github.com/snyk/vervet/v6@v6.2.4/ref_alias_resolver.go (about) 1 package vervet 2 3 import ( 4 "reflect" 5 "strings" 6 7 "github.com/getkin/kin-openapi/openapi3" 8 "github.com/mitchellh/reflectwalk" 9 ) 10 11 // refAliasResolver rewrites references in an OpenAPI document object to local 12 // references, so that the spec is self-contained. 13 type refAliasResolver struct { 14 doc *openapi3.T 15 refAliases map[string]string 16 curRefType reflect.Value 17 curRefField reflect.Value 18 } 19 20 // newRefAliasResolver returns a new refAliasResolver. 21 func newRefAliasResolver(doc *openapi3.T) *refAliasResolver { 22 res := &refAliasResolver{doc: doc} 23 if doc.Components == nil { 24 return res 25 } 26 27 res.refAliases = make(map[string]string, len(doc.Components.Extensions)) 28 29 for refAlias, extValue := range doc.Components.Extensions { 30 contents, ok := extValue.(map[string]interface{}) 31 if !ok { 32 continue 33 } 34 ref, ok := contents["$ref"].(string) 35 if ok && ref != "" { 36 res.refAliases["#/components/"+refAlias] = ref 37 } 38 } 39 40 return res 41 } 42 43 func (l *refAliasResolver) resolveRefAlias(ref string) string { 44 if ref != "" && ref[0] == '#' { 45 for refAlias, refTarget := range l.refAliases { 46 if strings.HasPrefix(ref, refAlias) { 47 return strings.Replace(ref, refAlias, refTarget+"#", 1) 48 } 49 } 50 } 51 return ref 52 } 53 54 // resolve rewrites all references in the OpenAPI document to local references. 55 func (l *refAliasResolver) resolve() error { 56 return reflectwalk.Walk(l.doc, l) 57 } 58 59 // Struct implements reflectwalk.StructWalker. 60 func (l *refAliasResolver) Struct(v reflect.Value) error { 61 l.curRefType, l.curRefField = v, v.FieldByName("Ref") 62 return nil 63 } 64 65 // StructField implements reflectwalk.StructWalker. 66 func (l *refAliasResolver) StructField(sf reflect.StructField, v reflect.Value) error { 67 if !l.curRefField.IsValid() { 68 return nil 69 } 70 ref := l.curRefField.String() 71 if ref == "" { 72 return nil 73 } 74 ref = l.resolveRefAlias(ref) 75 l.curRefField.Set(reflect.ValueOf(ref)) 76 return nil 77 }