github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/server/grpc/extractor.go (about) 1 // Copyright 2020 Asim Aslam 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Original source: github.com/micro/go-micro/v3/server/grpc/extractor.go 16 17 package grpc 18 19 import ( 20 "fmt" 21 "reflect" 22 "strings" 23 24 "github.com/tickoalcantara12/micro/v3/service/registry" 25 ) 26 27 func extractValue(v reflect.Type, d int) *registry.Value { 28 if d == 6 { 29 return nil 30 } 31 if v == nil { 32 return nil 33 } 34 35 if v.Kind() == reflect.Ptr { 36 v = v.Elem() 37 } 38 39 // slices and maps don't have a defined name 40 if v.Kind() != reflect.Slice && v.Kind() != reflect.Map && len(v.Name()) == 0 { 41 return nil 42 } 43 44 arg := ®istry.Value{ 45 Name: v.Name(), 46 Type: v.Name(), 47 } 48 49 switch v.Kind() { 50 case reflect.Struct: 51 for i := 0; i < v.NumField(); i++ { 52 f := v.Field(i) 53 val := extractValue(f.Type, d+1) 54 if val == nil { 55 continue 56 } 57 58 // if we can find a json tag use it 59 if tags := f.Tag.Get("json"); len(tags) > 0 { 60 parts := strings.Split(tags, ",") 61 if parts[0] == "-" || parts[0] == "omitempty" { 62 continue 63 } 64 val.Name = parts[0] 65 } else { 66 continue 67 } 68 69 // if there's no name default it 70 if len(val.Name) == 0 { 71 continue 72 } 73 74 arg.Values = append(arg.Values, val) 75 } 76 case reflect.Slice: 77 p := v.Elem() 78 if p.Kind() == reflect.Ptr { 79 p = p.Elem() 80 } 81 arg.Type = "[]" + p.Name() 82 case reflect.Map: 83 p := v.Elem() 84 if p.Kind() == reflect.Ptr { 85 p = p.Elem() 86 } 87 key := v.Key() 88 if key.Kind() == reflect.Ptr { 89 key = key.Elem() 90 } 91 92 arg.Type = fmt.Sprintf("map[%s]%s", key.Name(), p.Name()) 93 94 } 95 96 return arg 97 } 98 99 func extractEndpoint(method reflect.Method) *registry.Endpoint { 100 if method.PkgPath != "" { 101 return nil 102 } 103 104 var rspType, reqType reflect.Type 105 var stream bool 106 mt := method.Type 107 108 switch mt.NumIn() { 109 case 3: 110 reqType = mt.In(1) 111 rspType = mt.In(2) 112 case 4: 113 reqType = mt.In(2) 114 rspType = mt.In(3) 115 default: 116 return nil 117 } 118 119 // are we dealing with a stream? 120 switch rspType.Kind() { 121 case reflect.Func, reflect.Interface: 122 stream = true 123 } 124 125 request := extractValue(reqType, 0) 126 response := extractValue(rspType, 0) 127 128 ep := ®istry.Endpoint{ 129 Name: method.Name, 130 Request: request, 131 Response: response, 132 Metadata: make(map[string]string), 133 } 134 135 if stream { 136 ep.Metadata = map[string]string{ 137 "stream": fmt.Sprintf("%v", stream), 138 } 139 } 140 141 return ep 142 } 143 144 func extractSubValue(typ reflect.Type) *registry.Value { 145 var reqType reflect.Type 146 switch typ.NumIn() { 147 case 1: 148 reqType = typ.In(0) 149 case 2: 150 reqType = typ.In(1) 151 case 3: 152 reqType = typ.In(2) 153 default: 154 return nil 155 } 156 return extractValue(reqType, 0) 157 }