github.com/micro/go-micro/v2@v2.9.1/client/grpc/codec.go (about)

     1  package grpc
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  
     8  	b "bytes"
     9  
    10  	"github.com/golang/protobuf/jsonpb"
    11  	"github.com/golang/protobuf/proto"
    12  	"github.com/micro/go-micro/v2/codec"
    13  	"github.com/micro/go-micro/v2/codec/bytes"
    14  	"github.com/oxtoacart/bpool"
    15  	"google.golang.org/grpc"
    16  	"google.golang.org/grpc/encoding"
    17  )
    18  
    19  type jsonCodec struct{}
    20  type protoCodec struct{}
    21  type bytesCodec struct{}
    22  type wrapCodec struct{ encoding.Codec }
    23  
    24  var jsonpbMarshaler = &jsonpb.Marshaler{}
    25  var useNumber bool
    26  
    27  // create buffer pool with 16 instances each preallocated with 256 bytes
    28  var bufferPool = bpool.NewSizedBufferPool(16, 256)
    29  
    30  var (
    31  	defaultGRPCCodecs = map[string]encoding.Codec{
    32  		"application/json":         jsonCodec{},
    33  		"application/proto":        protoCodec{},
    34  		"application/protobuf":     protoCodec{},
    35  		"application/octet-stream": protoCodec{},
    36  		"application/grpc":         protoCodec{},
    37  		"application/grpc+json":    jsonCodec{},
    38  		"application/grpc+proto":   protoCodec{},
    39  		"application/grpc+bytes":   bytesCodec{},
    40  	}
    41  )
    42  
    43  // UseNumber fix unmarshal Number(8234567890123456789) to interface(8.234567890123457e+18)
    44  func UseNumber() {
    45  	useNumber = true
    46  }
    47  
    48  func (w wrapCodec) String() string {
    49  	return w.Codec.Name()
    50  }
    51  
    52  func (w wrapCodec) Marshal(v interface{}) ([]byte, error) {
    53  	b, ok := v.(*bytes.Frame)
    54  	if ok {
    55  		return b.Data, nil
    56  	}
    57  	return w.Codec.Marshal(v)
    58  }
    59  
    60  func (w wrapCodec) Unmarshal(data []byte, v interface{}) error {
    61  	b, ok := v.(*bytes.Frame)
    62  	if ok {
    63  		b.Data = data
    64  		return nil
    65  	}
    66  	return w.Codec.Unmarshal(data, v)
    67  }
    68  
    69  func (protoCodec) Marshal(v interface{}) ([]byte, error) {
    70  	switch m := v.(type) {
    71  	case *bytes.Frame:
    72  		return m.Data, nil
    73  	case proto.Message:
    74  		return proto.Marshal(m)
    75  	}
    76  	return nil, fmt.Errorf("failed to marshal: %v is not type of *bytes.Frame or proto.Message", v)
    77  }
    78  
    79  func (protoCodec) Unmarshal(data []byte, v interface{}) error {
    80  	m, ok := v.(proto.Message)
    81  	if !ok {
    82  		return fmt.Errorf("failed to unmarshal: %v is not type of proto.Message", v)
    83  	}
    84  	return proto.Unmarshal(data, m)
    85  }
    86  
    87  func (protoCodec) Name() string {
    88  	return "proto"
    89  }
    90  
    91  func (bytesCodec) Marshal(v interface{}) ([]byte, error) {
    92  	b, ok := v.(*[]byte)
    93  	if !ok {
    94  		return nil, fmt.Errorf("failed to marshal: %v is not type of *[]byte", v)
    95  	}
    96  	return *b, nil
    97  }
    98  
    99  func (bytesCodec) Unmarshal(data []byte, v interface{}) error {
   100  	b, ok := v.(*[]byte)
   101  	if !ok {
   102  		return fmt.Errorf("failed to unmarshal: %v is not type of *[]byte", v)
   103  	}
   104  	*b = data
   105  	return nil
   106  }
   107  
   108  func (bytesCodec) Name() string {
   109  	return "bytes"
   110  }
   111  
   112  func (jsonCodec) Marshal(v interface{}) ([]byte, error) {
   113  	if b, ok := v.(*bytes.Frame); ok {
   114  		return b.Data, nil
   115  	}
   116  
   117  	if pb, ok := v.(proto.Message); ok {
   118  		buf := bufferPool.Get()
   119  		defer bufferPool.Put(buf)
   120  		if err := jsonpbMarshaler.Marshal(buf, pb); err != nil {
   121  			return nil, err
   122  		}
   123  		return buf.Bytes(), nil
   124  	}
   125  
   126  	return json.Marshal(v)
   127  }
   128  
   129  func (jsonCodec) Unmarshal(data []byte, v interface{}) error {
   130  	if len(data) == 0 {
   131  		return nil
   132  	}
   133  	if b, ok := v.(*bytes.Frame); ok {
   134  		b.Data = data
   135  		return nil
   136  	}
   137  	if pb, ok := v.(proto.Message); ok {
   138  		return jsonpb.Unmarshal(b.NewReader(data), pb)
   139  	}
   140  
   141  	dec := json.NewDecoder(b.NewReader(data))
   142  	if useNumber {
   143  		dec.UseNumber()
   144  	}
   145  	return dec.Decode(v)
   146  }
   147  
   148  func (jsonCodec) Name() string {
   149  	return "json"
   150  }
   151  
   152  type grpcCodec struct {
   153  	// headers
   154  	id       string
   155  	target   string
   156  	method   string
   157  	endpoint string
   158  
   159  	s grpc.ClientStream
   160  	c encoding.Codec
   161  }
   162  
   163  func (g *grpcCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error {
   164  	md, err := g.s.Header()
   165  	if err != nil {
   166  		return err
   167  	}
   168  	if m == nil {
   169  		m = new(codec.Message)
   170  	}
   171  	if m.Header == nil {
   172  		m.Header = make(map[string]string, len(md))
   173  	}
   174  	for k, v := range md {
   175  		m.Header[k] = strings.Join(v, ",")
   176  	}
   177  	m.Id = g.id
   178  	m.Target = g.target
   179  	m.Method = g.method
   180  	m.Endpoint = g.endpoint
   181  	return nil
   182  }
   183  
   184  func (g *grpcCodec) ReadBody(v interface{}) error {
   185  	if f, ok := v.(*bytes.Frame); ok {
   186  		return g.s.RecvMsg(f)
   187  	}
   188  	return g.s.RecvMsg(v)
   189  }
   190  
   191  func (g *grpcCodec) Write(m *codec.Message, v interface{}) error {
   192  	// if we don't have a body
   193  	if v != nil {
   194  		return g.s.SendMsg(v)
   195  	}
   196  	// write the body using the framing codec
   197  	return g.s.SendMsg(&bytes.Frame{Data: m.Body})
   198  }
   199  
   200  func (g *grpcCodec) Close() error {
   201  	return g.s.CloseSend()
   202  }
   203  
   204  func (g *grpcCodec) String() string {
   205  	return g.c.Name()
   206  }