rpc.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Author: NiuJiuRu
  2. // Email: niujiuru@qq.com
  3. package jsonrpc2
  4. import (
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. )
  9. type ErrCode int
  10. const (
  11. ErrParse ErrCode = -32700 // "Parse error"
  12. ErrInvalidRequest ErrCode = -32600 // "Invalid request"
  13. ErrMethodNotFound ErrCode = -32601 // "Method not found"
  14. ErrInvalidParams ErrCode = -32602 // "Invalid params"
  15. ErrInternal ErrCode = -32603 // "Internal error"
  16. )
  17. type Error struct {
  18. Code ErrCode `json:"code"` //// 错误码
  19. Message string `json:"message"` //// 错误信息
  20. }
  21. func (e Error) Error() string {
  22. return e.Message
  23. }
  24. var errMessages = map[ErrCode]string{
  25. ErrParse: "Parse error", // 解析错误
  26. ErrInvalidRequest: "Invalid request", // 无效请求
  27. ErrMethodNotFound: "Method not found", // 无效方法
  28. ErrInvalidParams: "Invalid params", // 无效参数
  29. ErrInternal: "Internal error", // 内部错误
  30. }
  31. type Request struct {
  32. JSONRPC string `json:"jsonrpc"` // 版本号, 固定: "2.0"
  33. Method string `json:"method"` // 调用方法, 执行函数名
  34. Params json.RawMessage `json:"params,omitempty"` // 请求参数, 可选可为空
  35. ID *int `json:"id,omitempty"` // 请求ID, 用于标识请求
  36. }
  37. type Response struct {
  38. JSONRPC string `json:"jsonrpc"` // 版本号, 固定: "2.0"
  39. Result json.RawMessage `json:"result,omitempty"` // 响应结果, 可选可为空
  40. Error *Error `json:"error,omitempty"` // 错误信息, 可选可为空
  41. ID *int `json:"id"` // 应答ID, 响应匹配请求
  42. }
  43. // 解析请求数据
  44. func ParseRequest(input any) (*Request, error) {
  45. var raw []byte
  46. switch v := input.(type) {
  47. case nil:
  48. return nil, errors.New("input is nil")
  49. case string:
  50. raw = []byte(v)
  51. case []byte:
  52. raw = v
  53. default:
  54. return nil, errors.New("unsupported input type: must be string or []byte")
  55. }
  56. var req Request
  57. if err := json.Unmarshal(raw, &req); err != nil {
  58. return nil, fmt.Errorf("unmarshal request: %w", err)
  59. }
  60. return &req, nil
  61. }
  62. // 解析应答数据
  63. func ParseResponse(input any) (*Response, error) {
  64. var raw []byte
  65. switch v := input.(type) {
  66. case nil:
  67. return nil, errors.New("input is nil")
  68. case string:
  69. raw = []byte(v)
  70. case []byte:
  71. raw = v
  72. default:
  73. return nil, errors.New("unsupported input type: must be string or []byte")
  74. }
  75. var resp Response
  76. if err := json.Unmarshal(raw, &resp); err != nil {
  77. return nil, fmt.Errorf("unmarshal response: %w", err)
  78. }
  79. if resp.ID == nil {
  80. if resp.Error == nil || resp.Error.Code != ErrParse {
  81. return nil, errors.New(`response must contain an "id" field`)
  82. }
  83. }
  84. if resp.Error == nil && resp.Result == nil {
  85. return nil, errors.New(`response must contain either "result" or "error" field`)
  86. }
  87. if resp.Error != nil && resp.Result != nil {
  88. return nil, errors.New(`response can't contain both "result" and "error" field`)
  89. }
  90. return &resp, nil
  91. }
  92. // 编码JSON数据
  93. func marshalJSON(input any) (json.RawMessage, error) {
  94. switch v := input.(type) {
  95. case nil:
  96. return nil, nil
  97. case []byte:
  98. return nil, errors.New("[]byte is not allowed: use json.RawMessage for raw JSON")
  99. case json.RawMessage:
  100. return v, nil
  101. default:
  102. b, err := json.Marshal(v)
  103. if err != nil {
  104. return nil, fmt.Errorf("marshal json: %w", err)
  105. }
  106. return json.RawMessage(b), nil
  107. }
  108. }
  109. // 构建一个请求
  110. func BuildRequest(method string, params any, id int) (*Request, error) {
  111. if method == "" {
  112. return nil, errors.New("method must be non-empty")
  113. }
  114. raw, err := marshalJSON(params)
  115. if err != nil {
  116. return nil, err
  117. }
  118. req := &Request{
  119. JSONRPC: "2.0",
  120. Method: method,
  121. ID: &id,
  122. }
  123. if raw != nil { // 非空参数
  124. req.Params = raw
  125. }
  126. return req, nil
  127. }
  128. // 构建一个通知
  129. func BuildNotification(method string, params any) (*Request, error) {
  130. if method == "" {
  131. return nil, errors.New("method must be non-empty")
  132. }
  133. raw, err := marshalJSON(params)
  134. if err != nil {
  135. return nil, err
  136. }
  137. req := &Request{
  138. JSONRPC: "2.0",
  139. Method: method,
  140. }
  141. if raw != nil { // 非空参数
  142. req.Params = raw
  143. }
  144. return req, nil
  145. }
  146. // 构建成功应答
  147. func BuildResult(req *Request, result any) (*Response, error) {
  148. if req.ID == nil { // 通知类型, 不用应答
  149. return nil, nil
  150. }
  151. raw, err := marshalJSON(result)
  152. if err != nil {
  153. return nil, err
  154. }
  155. if raw == nil {
  156. raw = json.RawMessage("null")
  157. }
  158. return &Response{
  159. JSONRPC: "2.0",
  160. Result: raw,
  161. ID: req.ID,
  162. }, nil
  163. }
  164. // 构建错误应答
  165. func BuildError(req *Request, code ErrCode, message string) *Response {
  166. id := (*int)(nil)
  167. if code != ErrParse && req != nil && req.ID != nil {
  168. id = req.ID
  169. }
  170. emsg, ok := errMessages[code]
  171. if !ok {
  172. emsg = message
  173. }
  174. return &Response{
  175. JSONRPC: "2.0",
  176. Error: &Error{
  177. Code: code,
  178. Message: emsg,
  179. },
  180. ID: id,
  181. }
  182. }
  183. // 请求转字符串
  184. func (req *Request) String() (string, error) {
  185. b, err := json.Marshal(req)
  186. if err != nil {
  187. return "", fmt.Errorf("marshal request: %w", err)
  188. }
  189. return string(b), nil
  190. }
  191. // 应答转字符串
  192. func (resp *Response) String() (string, error) {
  193. b, err := json.Marshal(resp)
  194. if err != nil {
  195. return "", fmt.Errorf("marshal response: %w", err)
  196. }
  197. return string(b), nil
  198. }