gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/server/rpc_codec.go (about) 1 package server 2 3 import ( 4 "bytes" 5 "sync" 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/transport" 15 "github.com/oxtoacart/bpool" 16 "github.com/pkg/errors" 17 ) 18 19 type rpcCodec struct { 20 socket transport.Socket 21 codec codec.Codec 22 protocol string 23 24 req *transport.Message 25 buf *readWriteCloser 26 27 // check if we're the first 28 sync.RWMutex 29 first chan bool 30 } 31 32 type readWriteCloser struct { 33 sync.RWMutex 34 wbuf *bytes.Buffer 35 rbuf *bytes.Buffer 36 } 37 38 var ( 39 DefaultContentType = "application/protobuf" 40 41 DefaultCodecs = map[string]codec.NewCodec{ 42 "application/grpc": grpc.NewCodec, 43 "application/grpc+json": grpc.NewCodec, 44 "application/grpc+proto": grpc.NewCodec, 45 "application/json": json.NewCodec, 46 "application/json-rpc": jsonrpc.NewCodec, 47 "application/protobuf": proto.NewCodec, 48 "application/proto-rpc": protorpc.NewCodec, 49 "application/octet-stream": raw.NewCodec, 50 } 51 52 // TODO: remove legacy codec list 53 defaultCodecs = map[string]codec.NewCodec{ 54 "application/json": jsonrpc.NewCodec, 55 "application/json-rpc": jsonrpc.NewCodec, 56 "application/protobuf": protorpc.NewCodec, 57 "application/proto-rpc": protorpc.NewCodec, 58 "application/octet-stream": protorpc.NewCodec, 59 } 60 61 // the local buffer pool 62 bufferPool = bpool.NewSizedBufferPool(32, 1) 63 ) 64 65 func (rwc *readWriteCloser) Read(p []byte) (n int, err error) { 66 rwc.RLock() 67 defer rwc.RUnlock() 68 return rwc.rbuf.Read(p) 69 } 70 71 func (rwc *readWriteCloser) Write(p []byte) (n int, err error) { 72 rwc.Lock() 73 defer rwc.Unlock() 74 return rwc.wbuf.Write(p) 75 } 76 77 func (rwc *readWriteCloser) Close() error { 78 return nil 79 } 80 81 func getHeader(hdr string, md map[string]string) string { 82 if hd := md[hdr]; len(hd) > 0 { 83 return hd 84 } 85 return md["X-"+hdr] 86 } 87 88 func getHeaders(m *codec.Message) { 89 set := func(v, hdr string) string { 90 if len(v) > 0 { 91 return v 92 } 93 return m.Header[hdr] 94 } 95 96 m.Id = set(m.Id, "Micro-Id") 97 m.Error = set(m.Error, "Micro-Error") 98 m.Endpoint = set(m.Endpoint, "Micro-Endpoint") 99 m.Method = set(m.Method, "Micro-Method") 100 m.Target = set(m.Target, "Micro-Service") 101 102 // TODO: remove this cruft 103 if len(m.Endpoint) == 0 { 104 m.Endpoint = m.Method 105 } 106 } 107 108 func setHeaders(m, r *codec.Message) { 109 set := func(hdr, v string) { 110 if len(v) == 0 { 111 return 112 } 113 m.Header[hdr] = v 114 m.Header["X-"+hdr] = v 115 } 116 117 // set headers 118 set("Micro-Id", r.Id) 119 set("Micro-Service", r.Target) 120 set("Micro-Method", r.Method) 121 set("Micro-Endpoint", r.Endpoint) 122 set("Micro-Error", r.Error) 123 } 124 125 // setupProtocol sets up the old protocol 126 func setupProtocol(msg *transport.Message) codec.NewCodec { 127 service := getHeader("Micro-Service", msg.Header) 128 method := getHeader("Micro-Method", msg.Header) 129 endpoint := getHeader("Micro-Endpoint", msg.Header) 130 protocol := getHeader("Micro-Protocol", msg.Header) 131 target := getHeader("Micro-Target", msg.Header) 132 topic := getHeader("Micro-Topic", msg.Header) 133 134 // if the protocol exists (mucp) do nothing 135 if len(protocol) > 0 { 136 return nil 137 } 138 139 // newer method of processing messages over transport 140 if len(topic) > 0 { 141 return nil 142 } 143 144 // if no service/method/endpoint then it's the old protocol 145 if len(service) == 0 && len(method) == 0 && len(endpoint) == 0 { 146 return defaultCodecs[msg.Header["Content-Type"]] 147 } 148 149 // old target method specified 150 if len(target) > 0 { 151 return defaultCodecs[msg.Header["Content-Type"]] 152 } 153 154 // no method then set to endpoint 155 if len(method) == 0 { 156 msg.Header["Micro-Method"] = endpoint 157 } 158 159 // no endpoint then set to method 160 if len(endpoint) == 0 { 161 msg.Header["Micro-Endpoint"] = method 162 } 163 164 return nil 165 } 166 167 func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCodec) codec.Codec { 168 rwc := &readWriteCloser{ 169 rbuf: bufferPool.Get(), 170 wbuf: bufferPool.Get(), 171 } 172 173 r := &rpcCodec{ 174 buf: rwc, 175 codec: c(rwc), 176 req: req, 177 socket: socket, 178 protocol: "mucp", 179 first: make(chan bool), 180 } 181 182 // if grpc pre-load the buffer 183 // TODO: remove this terrible hack 184 switch r.codec.String() { 185 case "grpc": 186 // write the body 187 rwc.rbuf.Write(req.Body) 188 // set the protocol 189 r.protocol = "grpc" 190 default: 191 // first is not preloaded 192 close(r.first) 193 } 194 195 return r 196 } 197 198 func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { 199 // the initial message 200 m := codec.Message{ 201 Header: c.req.Header, 202 Body: c.req.Body, 203 } 204 205 // first message could be pre-loaded 206 select { 207 case <-c.first: 208 // not the first 209 var tm transport.Message 210 211 // read off the socket 212 if err := c.socket.Recv(&tm); err != nil { 213 return err 214 } 215 // reset the read buffer 216 c.buf.rbuf.Reset() 217 218 // write the body to the buffer 219 if _, err := c.buf.rbuf.Write(tm.Body); err != nil { 220 return err 221 } 222 223 // set the message header 224 m.Header = tm.Header 225 // set the message body 226 m.Body = tm.Body 227 228 // set req 229 c.req = &tm 230 default: 231 // we need to lock here to prevent race conditions 232 // and we make use of a channel otherwise because 233 // this does not result in a context switch 234 // locking to check c.first on every call to ReadHeader 235 // would otherwise drastically slow the code execution 236 c.Lock() 237 // recheck before closing because the select statement 238 // above is not thread safe, so thread safety here is 239 // mandatory 240 select { 241 case <-c.first: 242 default: 243 // disable first 244 close(c.first) 245 } 246 // now unlock and we never need this again 247 c.Unlock() 248 } 249 250 // set some internal things 251 getHeaders(&m) 252 253 // read header via codec 254 if err := c.codec.ReadHeader(&m, codec.Request); err != nil { 255 return err 256 } 257 258 // fallback for 0.14 and older 259 if len(m.Endpoint) == 0 { 260 m.Endpoint = m.Method 261 } 262 263 // set message 264 *r = m 265 266 return nil 267 } 268 269 func (c *rpcCodec) ReadBody(b interface{}) error { 270 // don't read empty body 271 if len(c.req.Body) == 0 { 272 return nil 273 } 274 // read raw data 275 if v, ok := b.(*raw.Frame); ok { 276 v.Data = c.req.Body 277 return nil 278 } 279 // decode the usual way 280 return c.codec.ReadBody(b) 281 } 282 283 func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { 284 c.buf.wbuf.Reset() 285 286 // create a new message 287 m := &codec.Message{ 288 Target: r.Target, 289 Method: r.Method, 290 Endpoint: r.Endpoint, 291 Id: r.Id, 292 Error: r.Error, 293 Type: r.Type, 294 Header: r.Header, 295 } 296 297 if m.Header == nil { 298 m.Header = map[string]string{} 299 } 300 301 setHeaders(m, r) 302 303 // the body being sent 304 var body []byte 305 306 // is it a raw frame? 307 if v, ok := b.(*raw.Frame); ok { 308 body = v.Data 309 // if we have encoded data just send it 310 } else if len(r.Body) > 0 { 311 body = r.Body 312 // write the body to codec 313 } else if err := c.codec.Write(m, b); err != nil { 314 c.buf.wbuf.Reset() 315 316 // write an error if it failed 317 m.Error = errors.Wrapf(err, "Unable to encode body").Error() 318 m.Header["Micro-Error"] = m.Error 319 // no body to write 320 if err := c.codec.Write(m, nil); err != nil { 321 return err 322 } 323 } else { 324 // set the body 325 body = c.buf.wbuf.Bytes() 326 } 327 328 // Set content type if theres content 329 if len(body) > 0 { 330 m.Header["Content-Type"] = c.req.Header["Content-Type"] 331 } 332 333 // send on the socket 334 return c.socket.Send(&transport.Message{ 335 Header: m.Header, 336 Body: body, 337 }) 338 } 339 340 func (c *rpcCodec) Close() error { 341 // close the codec 342 c.codec.Close() 343 // close the socket 344 err := c.socket.Close() 345 // put back the buffers 346 bufferPool.Put(c.buf.rbuf) 347 bufferPool.Put(c.buf.wbuf) 348 // return the error 349 return err 350 } 351 352 func (c *rpcCodec) String() string { 353 return c.protocol 354 }