github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/core/common/msgwriter/writer_jsonrpc2.go (about) 1 package msgwriter 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "github.com/nyan233/littlerpc/core/common/errorhandler" 7 "github.com/nyan233/littlerpc/core/common/jsonrpc2" 8 "github.com/nyan233/littlerpc/core/middle/codec" 9 errno "github.com/nyan233/littlerpc/core/protocol/error" 10 error2 "github.com/nyan233/littlerpc/core/protocol/error" 11 "github.com/nyan233/littlerpc/core/protocol/message" 12 "github.com/nyan233/littlerpc/core/utils/convert" 13 "strconv" 14 ) 15 16 type JsonRPC2 struct { 17 Codec codec.Codec 18 } 19 20 func NewJsonRPC2(writers ...Writer) Writer { 21 return &JsonRPC2{Codec: codec.Get("json")} 22 } 23 24 func (j *JsonRPC2) Header() []byte { 25 return []byte{jsonrpc2.Header} 26 } 27 28 func (j *JsonRPC2) Write(arg Argument, header byte) error2.LErrorDesc { 29 switch arg.Message.GetMsgType() { 30 case message.Call, message.ContextCancel: 31 return j.requestWrite(arg) 32 case message.Return: 33 return j.responseWrite(arg) 34 default: 35 return arg.EHandle.LNewErrorDesc(error2.UnsafeOption, 36 "jsonrpc2 not supported message type", arg.Message.GetMsgType()) 37 } 38 } 39 40 func (j *JsonRPC2) Reset() { 41 return 42 } 43 44 func (j *JsonRPC2) requestWrite(arg Argument) error2.LErrorDesc { 45 request := jsonrpc2.Request{ 46 BaseMessage: jsonrpc2.BaseMessage{ 47 MetaData: make(map[string]string, 16), 48 }, 49 } 50 request.MessageType = int(arg.Message.GetMsgType()) 51 request.Id = arg.Message.GetMsgId() 52 request.Version = jsonrpc2.Version 53 arg.Message.MetaData.Range(func(key, val string) bool { 54 request.MetaData[key] = val 55 return true 56 }) 57 request.Method = arg.Message.GetServiceName() 58 if arg.Encoder != nil && arg.Encoder.Scheme() != message.DefaultPacker { 59 return arg.EHandle.LNewErrorDesc(errno.UnsafeOption, "usage not supported for packer, only support text") 60 } 61 // json是文本型数据, 不需要base64编码, 如果是protobuf等二进制则需要base64编码之后才能被解析 62 var isJsonParams bool 63 if scheme := arg.Message.MetaData.Load(message.CodecScheme); scheme == "" || scheme == message.DefaultCodec { 64 isJsonParams = true 65 } 66 iter := arg.Message.PayloadsIterator() 67 request.Params = append(request.Params, '[') 68 for iter.Next() { 69 if !isJsonParams { 70 request.Params = append(request.Params, '"') 71 request.Params = append(request.Params, base64.StdEncoding.EncodeToString(iter.Take())...) 72 request.Params = append(request.Params, '"') 73 } else { 74 request.Params = append(request.Params, iter.Take()...) 75 } 76 if iter.Next() { 77 request.Params = append(request.Params, ',') 78 } 79 } 80 request.Params = append(request.Params, ']') 81 bytes, err := j.Codec.Marshal(&request) 82 if err != nil { 83 return arg.EHandle.LWarpErrorDesc(errorhandler.ErrMessageEncoding, 84 fmt.Sprintf("jsonrpc2 Marshal LRPCMessage failed: %v", err)) 85 } 86 writeN, err := arg.Conn.Write(bytes) 87 if err != nil { 88 return arg.EHandle.LWarpErrorDesc(errorhandler.ErrConnection, fmt.Sprintf("jsonrpc2 write failed: %v", err)) 89 } 90 if writeN != len(bytes) { 91 return arg.EHandle.LWarpErrorDesc(errorhandler.ErrConnection, fmt.Sprintf("jsonrpc2 write no complete: (%d:%d)", writeN, len(bytes))) 92 } 93 return nil 94 } 95 96 func (j *JsonRPC2) responseWrite(arg Argument) error2.LErrorDesc { 97 var rep jsonrpc2.Response 98 rep.MessageType = int(arg.Message.GetMsgType()) 99 errCode := arg.Message.MetaData.Load(message.ErrorCode) 100 errMessage := arg.Message.MetaData.Load(message.ErrorMessage) 101 errMore := arg.Message.MetaData.Load(message.ErrorMore) 102 if errCode != "" && errMessage != "" { 103 rep.Error = &jsonrpc2.Error{} 104 switch code, _ := strconv.Atoi(errCode); code { 105 case error2.ServiceNotFound: 106 rep.Error.Code = jsonrpc2.MethodNotFound 107 case error2.Success: 108 rep.Error = nil 109 goto handleResult 110 case error2.MessageDecodingFailed: 111 rep.Error.Code = jsonrpc2.ErrorParser 112 case error2.UnsafeOption: 113 rep.Error.Code = jsonrpc2.ErrorInternal 114 case error2.CallArgsTypeErr, error2.CodecMarshalErr: 115 rep.Error.Code = jsonrpc2.InvalidParams 116 case error2.Unknown: 117 rep.Error.Code = jsonrpc2.Unknown 118 } 119 rep.Error.Message = errMessage 120 rep.Error.Data = convert.StringToBytes(errMore) 121 } 122 handleResult: 123 iter := arg.Message.PayloadsIterator() 124 for iter.Next() { 125 rep.Result = append(rep.Result, iter.Take()) 126 } 127 rep.Id = arg.Message.GetMsgId() 128 rep.Version = jsonrpc2.Version 129 bytes, err := j.Codec.Marshal(rep) 130 if err != nil { 131 return arg.EHandle.LWarpErrorDesc(errorhandler.ErrMessageEncoding, 132 fmt.Sprintf("jsonrpc2 Marshal LRPCMessage failed: %v", err)) 133 } 134 writeN, err := arg.Conn.Write(bytes) 135 if err != nil { 136 return arg.EHandle.LWarpErrorDesc(errorhandler.ErrConnection, 137 fmt.Sprintf("JsonRpc2 NoMux write error: %v", err)) 138 } 139 if writeN != len(bytes) { 140 return arg.EHandle.LWarpErrorDesc(errorhandler.ErrConnection, 141 fmt.Sprintf("JsonRpc2 NoMux write bytes not equal : w(%d) != b(%d)", writeN, len(bytes))) 142 } 143 return nil 144 }