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  }