rpc.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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 *int64 `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 *int64 `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("request data is nil")
  49. case string:
  50. raw = []byte(v)
  51. case []byte:
  52. raw = v
  53. default:
  54. return nil, errors.New("unsupported request data 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. if req.JSONRPC != "2.0" {
  61. return nil, errors.New("invalid JSON-RPC version")
  62. }
  63. if req.Method == "" {
  64. return nil, errors.New("method cannot be empty")
  65. }
  66. return &req, nil
  67. }
  68. // 解析应答数据
  69. func ParseResponse(input any) (*Response, error) {
  70. var raw []byte
  71. switch v := input.(type) {
  72. case nil:
  73. return nil, errors.New("response data is nil")
  74. case string:
  75. raw = []byte(v)
  76. case []byte:
  77. raw = v
  78. default:
  79. return nil, errors.New("unsupported response data type: must be string or []byte")
  80. }
  81. var resp Response
  82. if err := json.Unmarshal(raw, &resp); err != nil {
  83. return nil, fmt.Errorf("unmarshal response: %w", err)
  84. }
  85. if resp.JSONRPC != "2.0" {
  86. return nil, errors.New("invalid JSON-RPC version")
  87. }
  88. // 情况 1:result 和 error 同时为空 → 错误
  89. if resp.Error == nil && resp.Result == nil {
  90. return nil, errors.New(`response must contain either "result" or "error" field`)
  91. }
  92. // 情况 2:result 和 error 同时存在 → 错误
  93. if resp.Error != nil && resp.Result != nil {
  94. return nil, errors.New(`response can't contain both "result" and "error" field`)
  95. }
  96. // 情况 3:成功时的应答 → 必须有id&且不能空
  97. if resp.Result != nil {
  98. if resp.ID == nil {
  99. return nil, errors.New(`"id" must exist and cannot be null for successful response`)
  100. }
  101. return &resp, nil
  102. }
  103. // 情况 4:错误时的应答 → 必须有id&且不能空
  104. if resp.Error != nil && resp.Error.Code == ErrParse { // 当发生解析错误时, "id"必须为: nil
  105. if resp.ID != nil {
  106. return nil, errors.New(`"id" must be null for parse error`)
  107. }
  108. return &resp, nil
  109. }
  110. if resp.ID == nil {
  111. return nil, errors.New(`"id" must exist and cannot be null for error response`)
  112. }
  113. return &resp, nil
  114. }
  115. // 编码JSON数据
  116. func marshalJSON(input any) (json.RawMessage, error) {
  117. switch v := input.(type) {
  118. case nil:
  119. return nil, nil
  120. case []byte:
  121. return nil, errors.New("[]byte is not allowed: use json.RawMessage for raw JSON")
  122. case json.RawMessage:
  123. return v, nil
  124. default:
  125. b, err := json.Marshal(v)
  126. if err != nil {
  127. return nil, fmt.Errorf("marshal json: %w", err)
  128. }
  129. return json.RawMessage(b), nil
  130. }
  131. }
  132. // 构建一个请求
  133. func BuildRequest(method string, params any, id ...int64) (*Request, error) {
  134. if method == "" {
  135. return nil, errors.New("method cannot be empty")
  136. }
  137. raw, err := marshalJSON(params)
  138. if err != nil {
  139. return nil, err
  140. }
  141. var rid int64
  142. if len(id) > 0 {
  143. rid = id[0]
  144. } else {
  145. rid = nextID()
  146. }
  147. req := &Request{
  148. JSONRPC: "2.0",
  149. Method: method,
  150. ID: &rid,
  151. }
  152. if raw != nil { // 非空参数
  153. req.Params = raw
  154. }
  155. return req, nil
  156. }
  157. // 构建一个通知
  158. func BuildNotification(method string, params any) (*Request, error) {
  159. if method == "" {
  160. return nil, errors.New("method cannot be empty")
  161. }
  162. raw, err := marshalJSON(params)
  163. if err != nil {
  164. return nil, err
  165. }
  166. req := &Request{
  167. JSONRPC: "2.0",
  168. Method: method,
  169. }
  170. if raw != nil { // 非空参数
  171. req.Params = raw
  172. }
  173. return req, nil
  174. }
  175. // 构建成功应答
  176. func BuildResult(req *Request, result any) (*Response, error) {
  177. if req.ID == nil { // 通知类型, 不用应答
  178. return nil, nil
  179. }
  180. raw, err := marshalJSON(result)
  181. if err != nil {
  182. return nil, err
  183. }
  184. if raw == nil {
  185. raw = json.RawMessage("null")
  186. }
  187. return &Response{
  188. JSONRPC: "2.0",
  189. Result: raw,
  190. ID: req.ID,
  191. }, nil
  192. }
  193. // 构建错误应答
  194. func BuildError(req *Request, code ErrCode, message string) *Response {
  195. id := (*int64)(nil)
  196. if req != nil {
  197. id = req.ID
  198. }
  199. if code == ErrParse {
  200. id = nil
  201. }
  202. emsg := message
  203. if emsg == "" {
  204. emsg = errMessages[code]
  205. }
  206. return &Response{
  207. JSONRPC: "2.0",
  208. Error: &Error{
  209. Code: code,
  210. Message: emsg,
  211. },
  212. ID: id,
  213. }
  214. }
  215. // 构建一个应答
  216. // 有错误时, result会被忽略; 没有错误时, error会被忽略
  217. func BuildResponse(req *Request, result any, err error) *Response {
  218. if err != nil {
  219. return BuildError(req, ErrInternal, err.Error())
  220. }
  221. resp, err := BuildResult(req, result)
  222. if err != nil {
  223. return BuildError(req, ErrInternal, "")
  224. }
  225. return resp
  226. }
  227. // 是否通知消息
  228. func (req *Request) IsNotification() bool {
  229. return req.ID == nil
  230. }
  231. // 请求转字符串
  232. func (req *Request) String() (string, error) {
  233. b, err := json.Marshal(req)
  234. if err != nil {
  235. return "", fmt.Errorf("marshal request: %w", err)
  236. }
  237. return string(b), nil
  238. }
  239. // 应答转字符串
  240. func (resp *Response) String() (string, error) {
  241. b, err := json.Marshal(resp)
  242. if err != nil {
  243. return "", fmt.Errorf("marshal response: %w", err)
  244. }
  245. return string(b), nil
  246. }