gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/client/rpc_codec.go (about) 1 package client 2 3 import ( 4 "bytes" 5 errs "errors" 6 7 "gitee.com/liuxuezhan/go-micro-v1.18.0/codec" 8 raw "gitee.com/liuxuezhan/go-micro-v1.18.0/codec/bytes" 9 "gitee.com/liuxuezhan/go-micro-v1.18.0/codec/grpc" 10 "gitee.com/liuxuezhan/go-micro-v1.18.0/codec/json" 11 "gitee.com/liuxuezhan/go-micro-v1.18.0/codec/jsonrpc" 12 "gitee.com/liuxuezhan/go-micro-v1.18.0/codec/proto" 13 "gitee.com/liuxuezhan/go-micro-v1.18.0/codec/protorpc" 14 "gitee.com/liuxuezhan/go-micro-v1.18.0/errors" 15 "gitee.com/liuxuezhan/go-micro-v1.18.0/registry" 16 "gitee.com/liuxuezhan/go-micro-v1.18.0/transport" 17 ) 18 19 const ( 20 lastStreamResponseError = "EOS" 21 ) 22 23 // serverError represents an error that has been returned from 24 // the remote side of the RPC connection. 25 type serverError string 26 27 func (e serverError) Error() string { 28 return string(e) 29 } 30 31 // errShutdown holds the specific error for closing/closed connections 32 var ( 33 errShutdown = errs.New("connection is shut down") 34 ) 35 36 type rpcCodec struct { 37 client transport.Client 38 codec codec.Codec 39 40 req *transport.Message 41 buf *readWriteCloser 42 43 // signify if its a stream 44 stream string 45 } 46 47 type readWriteCloser struct { 48 wbuf *bytes.Buffer 49 rbuf *bytes.Buffer 50 } 51 52 var ( 53 DefaultContentType = "application/protobuf" 54 55 DefaultCodecs = map[string]codec.NewCodec{ 56 "application/grpc": grpc.NewCodec, 57 "application/grpc+json": grpc.NewCodec, 58 "application/grpc+proto": grpc.NewCodec, 59 "application/protobuf": proto.NewCodec, 60 "application/json": json.NewCodec, 61 "application/json-rpc": jsonrpc.NewCodec, 62 "application/proto-rpc": protorpc.NewCodec, 63 "application/octet-stream": raw.NewCodec, 64 } 65 66 // TODO: remove legacy codec list 67 defaultCodecs = map[string]codec.NewCodec{ 68 "application/json": jsonrpc.NewCodec, 69 "application/json-rpc": jsonrpc.NewCodec, 70 "application/protobuf": protorpc.NewCodec, 71 "application/proto-rpc": protorpc.NewCodec, 72 "application/octet-stream": protorpc.NewCodec, 73 } 74 ) 75 76 func (rwc *readWriteCloser) Read(p []byte) (n int, err error) { 77 return rwc.rbuf.Read(p) 78 } 79 80 func (rwc *readWriteCloser) Write(p []byte) (n int, err error) { 81 return rwc.wbuf.Write(p) 82 } 83 84 func (rwc *readWriteCloser) Close() error { 85 rwc.rbuf.Reset() 86 rwc.wbuf.Reset() 87 return nil 88 } 89 90 func getHeaders(m *codec.Message) { 91 set := func(v, hdr string) string { 92 if len(v) > 0 { 93 return v 94 } 95 return m.Header[hdr] 96 } 97 98 // check error in header 99 m.Error = set(m.Error, "Micro-Error") 100 101 // check endpoint in header 102 m.Endpoint = set(m.Endpoint, "Micro-Endpoint") 103 104 // check method in header 105 m.Method = set(m.Method, "Micro-Method") 106 107 // set the request id 108 m.Id = set(m.Id, "Micro-Id") 109 } 110 111 func setHeaders(m *codec.Message, stream string) { 112 set := func(hdr, v string) { 113 if len(v) == 0 { 114 return 115 } 116 m.Header[hdr] = v 117 } 118 119 set("Micro-Id", m.Id) 120 set("Micro-Service", m.Target) 121 set("Micro-Method", m.Method) 122 set("Micro-Endpoint", m.Endpoint) 123 set("Micro-Error", m.Error) 124 125 if len(stream) > 0 { 126 set("Micro-Stream", stream) 127 } 128 } 129 130 // setupProtocol sets up the old protocol 131 func setupProtocol(msg *transport.Message, node *registry.Node) codec.NewCodec { 132 protocol := node.Metadata["protocol"] 133 134 // got protocol 135 if len(protocol) > 0 { 136 return nil 137 } 138 139 // processing topic publishing 140 if len(msg.Header["Micro-Topic"]) > 0 { 141 return nil 142 } 143 144 // no protocol use old codecs 145 switch msg.Header["Content-Type"] { 146 case "application/json": 147 msg.Header["Content-Type"] = "application/json-rpc" 148 case "application/protobuf": 149 msg.Header["Content-Type"] = "application/proto-rpc" 150 } 151 152 // now return codec 153 return defaultCodecs[msg.Header["Content-Type"]] 154 } 155 156 func newRpcCodec(req *transport.Message, client transport.Client, c codec.NewCodec, stream string) codec.Codec { 157 rwc := &readWriteCloser{ 158 wbuf: bytes.NewBuffer(nil), 159 rbuf: bytes.NewBuffer(nil), 160 } 161 r := &rpcCodec{ 162 buf: rwc, 163 client: client, 164 codec: c(rwc), 165 req: req, 166 stream: stream, 167 } 168 return r 169 } 170 171 func (c *rpcCodec) Write(m *codec.Message, body interface{}) error { 172 c.buf.wbuf.Reset() 173 174 // create header 175 if m.Header == nil { 176 m.Header = map[string]string{} 177 } 178 179 // copy original header 180 for k, v := range c.req.Header { 181 m.Header[k] = v 182 } 183 184 // set the mucp headers 185 setHeaders(m, c.stream) 186 187 // if body is bytes Frame don't encode 188 if body != nil { 189 b, ok := body.(*raw.Frame) 190 if ok { 191 // set body 192 m.Body = b.Data 193 body = nil 194 } 195 } 196 197 if len(m.Body) == 0 { 198 // write to codec 199 if err := c.codec.Write(m, body); err != nil { 200 return errors.InternalServerError("go.micro.client.codec", err.Error()) 201 } 202 // set body 203 m.Body = c.buf.wbuf.Bytes() 204 } 205 206 // create new transport message 207 msg := transport.Message{ 208 Header: m.Header, 209 Body: m.Body, 210 } 211 // send the request 212 if err := c.client.Send(&msg); err != nil { 213 return errors.InternalServerError("go.micro.client.transport", err.Error()) 214 } 215 return nil 216 } 217 218 func (c *rpcCodec) ReadHeader(m *codec.Message, r codec.MessageType) error { 219 var tm transport.Message 220 221 // read message from transport 222 if err := c.client.Recv(&tm); err != nil { 223 return errors.InternalServerError("go.micro.client.transport", err.Error()) 224 } 225 226 c.buf.rbuf.Reset() 227 c.buf.rbuf.Write(tm.Body) 228 229 // set headers from transport 230 m.Header = tm.Header 231 232 // read header 233 err := c.codec.ReadHeader(m, r) 234 235 // get headers 236 getHeaders(m) 237 238 // return header error 239 if err != nil { 240 return errors.InternalServerError("go.micro.client.codec", err.Error()) 241 } 242 243 return nil 244 } 245 246 func (c *rpcCodec) ReadBody(b interface{}) error { 247 // read body 248 // read raw data 249 if v, ok := b.(*raw.Frame); ok { 250 v.Data = c.buf.rbuf.Bytes() 251 return nil 252 } 253 254 if err := c.codec.ReadBody(b); err != nil { 255 return errors.InternalServerError("go.micro.client.codec", err.Error()) 256 } 257 return nil 258 } 259 260 func (c *rpcCodec) Close() error { 261 c.buf.Close() 262 c.codec.Close() 263 if err := c.client.Close(); err != nil { 264 return errors.InternalServerError("go.micro.client.transport", err.Error()) 265 } 266 return nil 267 } 268 269 func (c *rpcCodec) String() string { 270 return "rpc" 271 }