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 := &registry.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 := &registry.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  }