github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/server/grpc/codec.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/codec.go
    16  
    17  package grpc
    18  
    19  import (
    20  	"encoding/json"
    21  	"strings"
    22  
    23  	b "bytes"
    24  
    25  	"github.com/golang/protobuf/jsonpb"
    26  	"github.com/golang/protobuf/proto"
    27  	"github.com/tickoalcantara12/micro/v3/util/codec"
    28  	"github.com/tickoalcantara12/micro/v3/util/codec/bytes"
    29  	"google.golang.org/grpc"
    30  	"google.golang.org/grpc/encoding"
    31  	"google.golang.org/grpc/metadata"
    32  )
    33  
    34  type jsonCodec struct{}
    35  type bytesCodec struct{}
    36  type protoCodec struct{}
    37  type wrapCodec struct{ encoding.Codec }
    38  
    39  var jsonpbMarshaler = &jsonpb.Marshaler{
    40  	EnumsAsInts:  false,
    41  	EmitDefaults: true,
    42  	OrigName:     true,
    43  }
    44  
    45  var (
    46  	defaultGRPCCodecs = map[string]encoding.Codec{
    47  		"application/json":         jsonCodec{},
    48  		"application/proto":        protoCodec{},
    49  		"application/protobuf":     protoCodec{},
    50  		"application/octet-stream": protoCodec{},
    51  		"application/grpc":         protoCodec{},
    52  		"application/grpc+json":    jsonCodec{},
    53  		"application/grpc+proto":   protoCodec{},
    54  		"application/grpc+bytes":   bytesCodec{},
    55  		"multipart/form-data":      jsonCodec{},
    56  	}
    57  )
    58  
    59  func (w wrapCodec) String() string {
    60  	return w.Codec.Name()
    61  }
    62  
    63  func (w wrapCodec) Marshal(v interface{}) ([]byte, error) {
    64  	b, ok := v.(*bytes.Frame)
    65  	if ok {
    66  		return b.Data, nil
    67  	}
    68  	return w.Codec.Marshal(v)
    69  }
    70  
    71  func (w wrapCodec) Unmarshal(data []byte, v interface{}) error {
    72  	b, ok := v.(*bytes.Frame)
    73  	if ok {
    74  		b.Data = data
    75  		return nil
    76  	}
    77  	if v == nil {
    78  		return nil
    79  	}
    80  	return w.Codec.Unmarshal(data, v)
    81  }
    82  
    83  func (protoCodec) Marshal(v interface{}) ([]byte, error) {
    84  	m, ok := v.(proto.Message)
    85  	if !ok {
    86  		return nil, codec.ErrInvalidMessage
    87  	}
    88  	return proto.Marshal(m)
    89  }
    90  
    91  func (protoCodec) Unmarshal(data []byte, v interface{}) error {
    92  	m, ok := v.(proto.Message)
    93  	if !ok {
    94  		return codec.ErrInvalidMessage
    95  	}
    96  	return proto.Unmarshal(data, m)
    97  }
    98  
    99  func (protoCodec) Name() string {
   100  	return "proto"
   101  }
   102  
   103  func (jsonCodec) Marshal(v interface{}) ([]byte, error) {
   104  	if pb, ok := v.(proto.Message); ok {
   105  		s, err := jsonpbMarshaler.MarshalToString(pb)
   106  		return []byte(s), err
   107  	}
   108  
   109  	return json.Marshal(v)
   110  }
   111  
   112  func (jsonCodec) Unmarshal(data []byte, v interface{}) error {
   113  	if len(data) == 0 {
   114  		return nil
   115  	}
   116  	if pb, ok := v.(proto.Message); ok {
   117  		return jsonpb.Unmarshal(b.NewReader(data), pb)
   118  	}
   119  	return json.Unmarshal(data, v)
   120  }
   121  
   122  func (jsonCodec) Name() string {
   123  	return "json"
   124  }
   125  
   126  func (bytesCodec) Marshal(v interface{}) ([]byte, error) {
   127  	b, ok := v.(*[]byte)
   128  	if !ok {
   129  		return nil, codec.ErrInvalidMessage
   130  	}
   131  	return *b, nil
   132  }
   133  
   134  func (bytesCodec) Unmarshal(data []byte, v interface{}) error {
   135  	b, ok := v.(*[]byte)
   136  	if !ok {
   137  		return codec.ErrInvalidMessage
   138  	}
   139  	*b = data
   140  	return nil
   141  }
   142  
   143  func (bytesCodec) Name() string {
   144  	return "bytes"
   145  }
   146  
   147  type grpcCodec struct {
   148  	grpc.ServerStream
   149  	// headers
   150  	id       string
   151  	target   string
   152  	method   string
   153  	endpoint string
   154  
   155  	c encoding.Codec
   156  }
   157  
   158  func (g *grpcCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error {
   159  	md, _ := metadata.FromIncomingContext(g.ServerStream.Context())
   160  	if m == nil {
   161  		m = new(codec.Message)
   162  	}
   163  	if m.Header == nil {
   164  		m.Header = make(map[string]string, len(md))
   165  	}
   166  	for k, v := range md {
   167  		m.Header[k] = strings.Join(v, ",")
   168  	}
   169  	m.Id = g.id
   170  	m.Target = g.target
   171  	m.Method = g.method
   172  	m.Endpoint = g.endpoint
   173  	return nil
   174  }
   175  
   176  func (g *grpcCodec) ReadBody(v interface{}) error {
   177  	// caller has requested a frame
   178  	if f, ok := v.(*bytes.Frame); ok {
   179  		return g.ServerStream.RecvMsg(f)
   180  	}
   181  	return g.ServerStream.RecvMsg(v)
   182  }
   183  
   184  func (g *grpcCodec) Write(m *codec.Message, v interface{}) error {
   185  	// if we don't have a body
   186  	if v != nil {
   187  		b, err := g.c.Marshal(v)
   188  		if err != nil {
   189  			return err
   190  		}
   191  		m.Body = b
   192  	}
   193  	// write the body using the framing codec
   194  	return g.ServerStream.SendMsg(&bytes.Frame{Data: m.Body})
   195  }
   196  
   197  func (g *grpcCodec) Close() error {
   198  	return nil
   199  }
   200  
   201  func (g *grpcCodec) String() string {
   202  	return "grpc"
   203  }