go-micro.dev/v5@v5.12.0/server/extractor.go (about) 1 package server 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 8 "go-micro.dev/v5/registry" 9 ) 10 11 func extractValue(v reflect.Type, d int) *registry.Value { 12 if d == 3 { 13 return nil 14 } 15 if v == nil { 16 return nil 17 } 18 19 if v.Kind() == reflect.Ptr { 20 v = v.Elem() 21 } 22 23 arg := ®istry.Value{ 24 Name: v.Name(), 25 Type: v.Name(), 26 } 27 28 switch v.Kind() { 29 case reflect.Struct: 30 for i := 0; i < v.NumField(); i++ { 31 f := v.Field(i) 32 if f.PkgPath != "" { 33 continue 34 } 35 val := extractValue(f.Type, d+1) 36 if val == nil { 37 continue 38 } 39 40 // if we can find a json tag use it 41 if tags := f.Tag.Get("json"); len(tags) > 0 { 42 parts := strings.Split(tags, ",") 43 if parts[0] == "-" || parts[0] == "omitempty" { 44 continue 45 } 46 val.Name = parts[0] 47 } else { 48 val.Name = f.Name 49 } 50 51 // if there's no name default it 52 if len(val.Name) == 0 { 53 val.Name = v.Field(i).Name 54 } 55 56 // still no name then continue 57 if len(val.Name) == 0 { 58 continue 59 } 60 61 arg.Values = append(arg.Values, val) 62 } 63 case reflect.Slice: 64 p := v.Elem() 65 if p.Kind() == reflect.Ptr { 66 p = p.Elem() 67 } 68 arg.Type = "[]" + p.Name() 69 } 70 71 return arg 72 } 73 74 func extractEndpoint(method reflect.Method) *registry.Endpoint { 75 if method.PkgPath != "" { 76 return nil 77 } 78 79 var rspType, reqType reflect.Type 80 var stream bool 81 mt := method.Type 82 83 switch mt.NumIn() { 84 case 3: 85 reqType = mt.In(1) 86 rspType = mt.In(2) 87 case 4: 88 reqType = mt.In(2) 89 rspType = mt.In(3) 90 default: 91 return nil 92 } 93 94 // are we dealing with a stream? 95 switch rspType.Kind() { 96 case reflect.Func, reflect.Interface: 97 stream = true 98 } 99 100 request := extractValue(reqType, 0) 101 response := extractValue(rspType, 0) 102 103 ep := ®istry.Endpoint{ 104 Name: method.Name, 105 Request: request, 106 Response: response, 107 Metadata: make(map[string]string), 108 } 109 110 // set endpoint metadata for stream 111 if stream { 112 ep.Metadata = map[string]string{ 113 "stream": fmt.Sprintf("%v", stream), 114 } 115 } 116 117 return ep 118 } 119 120 func extractSubValue(typ reflect.Type) *registry.Value { 121 var reqType reflect.Type 122 switch typ.NumIn() { 123 case 1: 124 reqType = typ.In(0) 125 case 2: 126 reqType = typ.In(1) 127 case 3: 128 reqType = typ.In(2) 129 default: 130 return nil 131 } 132 return extractValue(reqType, 0) 133 }