1 // Copyright 2018 Adam S Levy
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to
5 // deal in the Software without restriction, including without limitation the
6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 // sell copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 // IN THE SOFTWARE.
20 21 package jsonrpc2
22 23 import "fmt"
24 25 // ErrorCode indicates the Error type that occurred.
26 //
27 // The error codes from and including -32768 to -32000 are reserved for
28 // pre-defined errors. Any code within this range, but not defined explicitly
29 // below is reserved for future use.
30 //
31 // See ErrorCodeMinReserved.
32 type ErrorCode int
33 34 // Official JSON-RPC 2.0 Spec Error Codes and Messages
35 const (
36 // ErrorCodeMinReserved is the minimum reserved error code. Method
37 // defined errors may be less than this value.
38 ErrorCodeMinReserved ErrorCode = -32768
39 40 // ErrorCodeParse means the received data was not valid JSON.
41 ErrorCodeParse ErrorCode = -32700
42 ErrorMessageParse = "Parse error"
43 44 // ErrorCodeInvalidRequest means the received valid JSON is not a valid
45 // Request object.
46 ErrorCodeInvalidRequest ErrorCode = -32600
47 ErrorMessageInvalidRequest = "Invalid Request"
48 49 // ErrorCodeMethodNotFound means the requested method is not defined
50 // for the HTTPRequestHandler.
51 ErrorCodeMethodNotFound ErrorCode = -32601
52 ErrorMessageMethodNotFound = "Method not found"
53 54 // ErrorCodeInvalidParams means a method is called with invalid method
55 // parameter(s).
56 //
57 // MethodFuncs are responsible for detecting and returning this error.
58 ErrorCodeInvalidParams ErrorCode = -32602
59 ErrorMessageInvalidParams = "Invalid params"
60 61 // ErrorCodeInternal means an internal error occurred such as a
62 // MethodFunc panic.
63 ErrorCodeInternal ErrorCode = -32603
64 ErrorMessageInternal = "Internal error"
65 66 // ErrorCodeMaxReserved is the maximum reserved error code. Method
67 // defined errors may be greater than this value.
68 ErrorCodeMaxReserved ErrorCode = -32000
69 )
70 71 // IsReserved returns true if c is within the reserved error code range:
72 // [LowestReservedErrorCode, HighestReservedErrorCode]
73 func (c ErrorCode) IsReserved() bool {
74 return ErrorCodeMinReserved <= c && c <= ErrorCodeMaxReserved
75 }
76 77 func (c ErrorCode) String() string {
78 if !c.IsReserved() {
79 return fmt.Sprintf("ErrorCode{%v}", int(c))
80 }
81 msg := "reserved"
82 switch c {
83 case ErrorCodeParse:
84 msg = ErrorMessageParse
85 case ErrorCodeInvalidRequest:
86 msg = ErrorMessageInvalidRequest
87 case ErrorCodeMethodNotFound:
88 msg = ErrorMessageMethodNotFound
89 case ErrorCodeInvalidParams:
90 msg = ErrorMessageInvalidParams
91 case ErrorCodeInternal:
92 msg = ErrorMessageInternal
93 }
94 return fmt.Sprintf("ErrorCode{%v:%q}", int(c), msg)
95 }
96 97 // Error represents a JSON-RPC 2.0 Error object, which is used in the Response
98 // object. MethodFuncs may return an Error or *Error to return an Error
99 // Response to the client.
100 type Error struct {
101 // Code is a number that indicates the error type that occurred.
102 Code ErrorCode `json:"code"`
103 104 // Message is a short description of the error. The message SHOULD be
105 // limited to a concise single sentence.
106 Message string `json:"message"`
107 108 // Data is a Primitive or Structured value that contains additional
109 // information about the error. This may be omitted. The value of this
110 // member is defined by the Server (e.g. detailed error information,
111 // nested errors etc.).
112 Data interface{} `json:"data,omitempty"`
113 }
114 115 // Error implements the error interface.
116 func (e Error) Error() string {
117 s := fmt.Sprintf("jsonrpc2.Error{Code:%v, Message:%q", e.Code, e.Message)
118 if e.Data != nil {
119 s += fmt.Sprintf(", Data:%#v", e.Data)
120 }
121 return s + "}"
122 }
123 124 // IsZero reports whether e is zero valued.
125 func (e Error) IsZero() bool {
126 return e == Error{}
127 }
128 129 // NewError returns an Error with code, msg, and data.
130 //
131 // The data must not cause an error when passed to json.Marshal, else any
132 // MethodFunc returning it will return an Internal Error to clients instead.
133 //
134 // If data is type error, then the Error() string is used instead, since
135 // otherwise the error may not json.Marshal properly.
136 func NewError(code ErrorCode, msg string, data interface{}) Error {
137 if err, ok := data.(error); ok {
138 data = err.Error()
139 }
140 return Error{code, msg, data}
141 }
142 143 // ErrorInvalidParams returns
144 // NewError(ErrorCodeInvalidParams, ErrorMessageInvalidParams, data)
145 //
146 // MethodFuncs are responsible for detecting invalid parameters and returning
147 // this error.
148 func ErrorInvalidParams(data interface{}) Error {
149 return NewError(ErrorCodeInvalidParams, ErrorMessageInvalidParams, data)
150 }
151 152 func errorInternal(data interface{}) Error {
153 return NewError(ErrorCodeInternal, ErrorMessageInternal, data)
154 }
155 func errorParse(data interface{}) Error {
156 return NewError(ErrorCodeParse, ErrorMessageParse, data)
157 }
158 func errorInvalidRequest(data interface{}) Error {
159 return NewError(ErrorCodeInvalidRequest, ErrorMessageInvalidRequest, data)
160 }
161 func errorMethodNotFound(data interface{}) Error {
162 return NewError(ErrorCodeMethodNotFound, ErrorMessageMethodNotFound, data)
163 }
164