github.com/snyk/vervet/v3@v3.7.0/ref_alias_resolver.go (about) 1 package vervet 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "strings" 7 8 "github.com/getkin/kin-openapi/jsoninfo" 9 "github.com/getkin/kin-openapi/openapi3" 10 "github.com/mitchellh/reflectwalk" 11 ) 12 13 // refAliasResolver rewrites references in an OpenAPI document object to local 14 // references, so that the spec is self-contained. 15 type refAliasResolver struct { 16 doc *openapi3.T 17 refAliases map[string]string 18 curRefType reflect.Value 19 curRefField reflect.Value 20 } 21 22 // newRefAliasResolver returns a new refAliasResolver. 23 func newRefAliasResolver(doc *openapi3.T) (*refAliasResolver, error) { 24 refAliases := map[string]string{} 25 for refAlias, extValue := range doc.Components.ExtensionProps.Extensions { 26 contents, ok := extValue.(json.RawMessage) 27 if !ok { 28 continue 29 } 30 dec, err := jsoninfo.NewObjectDecoder(contents) 31 if err != nil { 32 return nil, err 33 } 34 var ref openapi3.Ref 35 if err := doc.Components.ExtensionProps.DecodeWith(dec, &ref); err == nil && ref.Ref != "" { 36 refAliases["#/components/"+refAlias] = ref.Ref 37 } 38 } 39 40 return &refAliasResolver{doc: doc, refAliases: refAliases}, nil 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 }