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