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