@@ -50,8 +50,9 @@ type request struct {
5050const DEFAULT_MAX_REQUEST_SIZE = 100 << 20 // 100 MiB
5151
5252type respError struct {
53- Code int `json:"code"`
54- Message string `json:"message"`
53+ Code ErrorCode `json:"code"`
54+ Message string `json:"message"`
55+ Meta json.RawMessage `json:"meta,omitempty"`
5556}
5657
5758func (e * respError ) Error () string {
@@ -61,6 +62,31 @@ func (e *respError) Error() string {
6162 return e .Message
6263}
6364
65+ var marshalableRT = reflect .TypeOf (new (marshalable )).Elem ()
66+
67+ func (e * respError ) val (errors * Errors ) reflect.Value {
68+ if errors != nil {
69+ t , ok := errors .byCode [e .Code ]
70+ if ok {
71+ var v reflect.Value
72+ if t .Kind () == reflect .Ptr {
73+ v = reflect .New (t .Elem ())
74+ } else {
75+ v = reflect .New (t )
76+ }
77+ if len (e .Meta ) > 0 && v .Type ().Implements (marshalableRT ) {
78+ _ = v .Interface ().(marshalable ).UnmarshalJSON (e .Meta )
79+ }
80+ if t .Kind () != reflect .Ptr {
81+ v = v .Elem ()
82+ }
83+ return v
84+ }
85+ }
86+
87+ return reflect .ValueOf (e )
88+ }
89+
6490type response struct {
6591 Jsonrpc string `json:"jsonrpc"`
6692 Result interface {} `json:"result,omitempty"`
@@ -108,7 +134,7 @@ func (s *RPCServer) register(namespace string, r interface{}) {
108134
109135// Handle
110136
111- type rpcErrFunc func (w func (func (io.Writer )), req * request , code int , err error )
137+ type rpcErrFunc func (w func (func (io.Writer )), req * request , code ErrorCode , err error )
112138type chanOut func (reflect.Value , int64 ) error
113139
114140func (s * RPCServer ) handleReader (ctx context.Context , r io.Reader , w io.Writer , rpcError rpcErrFunc ) {
@@ -186,6 +212,30 @@ func (s *RPCServer) getSpan(ctx context.Context, req request) (context.Context,
186212 return ctx , nil
187213}
188214
215+ func (s * RPCServer ) createError (err error ) * respError {
216+ var code ErrorCode = 1
217+ if s .errors != nil {
218+ c , ok := s .errors .byType [reflect .TypeOf (err )]
219+ if ok {
220+ code = c
221+ }
222+ }
223+
224+ out := & respError {
225+ Code : code ,
226+ Message : err .(error ).Error (),
227+ }
228+
229+ if m , ok := err .(marshalable ); ok {
230+ meta , err := m .MarshalJSON ()
231+ if err == nil {
232+ out .Meta = meta
233+ }
234+ }
235+
236+ return out
237+ }
238+
189239func (s * RPCServer ) handle (ctx context.Context , req request , w func (func (io.Writer )), rpcError rpcErrFunc , done func (keepCtx bool ), chOut chanOut ) {
190240 // Not sure if we need to sanitize the incoming req.Method or not.
191241 ctx , span := s .getSpan (ctx , req )
@@ -278,10 +328,8 @@ func (s *RPCServer) handle(ctx context.Context, req request, w func(func(io.Writ
278328 if err != nil {
279329 log .Warnf ("error in RPC call to '%s': %+v" , req .Method , err )
280330 stats .Record (ctx , metrics .RPCResponseError .M (1 ))
281- resp .Error = & respError {
282- Code : 1 ,
283- Message : err .(error ).Error (),
284- }
331+
332+ resp .Error = s .createError (err .(error ))
285333 }
286334 }
287335
0 commit comments