github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/server/mucp/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/mucp/extractor.go 16 17 package mucp 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 == 3 { 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 arg := ®istry.Value{ 40 Name: v.Name(), 41 Type: v.Name(), 42 } 43 44 switch v.Kind() { 45 case reflect.Struct: 46 for i := 0; i < v.NumField(); i++ { 47 f := v.Field(i) 48 val := extractValue(f.Type, d+1) 49 if val == nil { 50 continue 51 } 52 53 // if we can find a json tag use it 54 if tags := f.Tag.Get("json"); len(tags) > 0 { 55 parts := strings.Split(tags, ",") 56 if parts[0] == "-" || parts[0] == "omitempty" { 57 continue 58 } 59 val.Name = parts[0] 60 } 61 62 // if there's no name default it 63 if len(val.Name) == 0 { 64 val.Name = v.Field(i).Name 65 } 66 67 // still no name then continue 68 if len(val.Name) == 0 { 69 continue 70 } 71 72 arg.Values = append(arg.Values, val) 73 } 74 case reflect.Slice: 75 p := v.Elem() 76 if p.Kind() == reflect.Ptr { 77 p = p.Elem() 78 } 79 arg.Type = "[]" + p.Name() 80 } 81 82 return arg 83 } 84 85 func extractEndpoint(method reflect.Method) *registry.Endpoint { 86 if method.PkgPath != "" { 87 return nil 88 } 89 90 var rspType, reqType reflect.Type 91 var stream bool 92 mt := method.Type 93 94 switch mt.NumIn() { 95 case 3: 96 reqType = mt.In(1) 97 rspType = mt.In(2) 98 case 4: 99 reqType = mt.In(2) 100 rspType = mt.In(3) 101 default: 102 return nil 103 } 104 105 // are we dealing with a stream? 106 switch rspType.Kind() { 107 case reflect.Func, reflect.Interface: 108 stream = true 109 } 110 111 request := extractValue(reqType, 0) 112 response := extractValue(rspType, 0) 113 114 ep := ®istry.Endpoint{ 115 Name: method.Name, 116 Request: request, 117 Response: response, 118 Metadata: make(map[string]string), 119 } 120 121 // set endpoint metadata for stream 122 if stream { 123 ep.Metadata = map[string]string{ 124 "stream": fmt.Sprintf("%v", stream), 125 } 126 } 127 128 return ep 129 } 130 131 func extractSubValue(typ reflect.Type) *registry.Value { 132 var reqType reflect.Type 133 switch typ.NumIn() { 134 case 1: 135 reqType = typ.In(0) 136 case 2: 137 reqType = typ.In(1) 138 case 3: 139 reqType = typ.In(2) 140 default: 141 return nil 142 } 143 return extractValue(reqType, 0) 144 }