mirror of
https://github.com/go-micro/go-micro.git
synced 2025-03-17 20:28:06 +02:00
93 lines
2.7 KiB
Go
93 lines
2.7 KiB
Go
package jsonrpc2
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
// Actual returned error may have different message.
|
|
errParse = NewError(-32700, "Parse error")
|
|
errRequest = NewError(-32600, "Invalid request")
|
|
errMethod = NewError(-32601, "Method not found")
|
|
errParams = NewError(-32602, "Invalid params")
|
|
errInternal = NewError(-32603, "Internal error")
|
|
errServer = NewError(-32000, "Server error")
|
|
errServerError = NewError(-32001, "jsonrpc2.Error: json.Marshal failed")
|
|
)
|
|
|
|
// Error represent JSON-RPC 2.0 "Error object".
|
|
type Error struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Data interface{} `json:"data,omitempty"`
|
|
}
|
|
|
|
// NewError returns an Error with given code and message.
|
|
func NewError(code int, message string) *Error {
|
|
return &Error{Code: code, Message: message}
|
|
}
|
|
|
|
// newError returns an Error with auto-detected code for given message.
|
|
func newError(message string) *Error {
|
|
switch {
|
|
case strings.HasPrefix(message, "rpc: service/method request ill-formed"):
|
|
return NewError(errMethod.Code, message)
|
|
case strings.HasPrefix(message, "rpc: can't find service"):
|
|
return NewError(errMethod.Code, message)
|
|
case strings.HasPrefix(message, "rpc: can't find method"):
|
|
return NewError(errMethod.Code, message)
|
|
default:
|
|
return NewError(errServer.Code, message)
|
|
}
|
|
}
|
|
|
|
// ServerError convert errors returned by Client.Call() into Error.
|
|
// User should check for rpc.ErrShutdown and io.ErrUnexpectedEOF before
|
|
// calling ServerError.
|
|
func ServerError(rpcerr error) *Error {
|
|
if rpcerr == nil {
|
|
return nil
|
|
}
|
|
if err, ok := rpcerr.(*Error); ok {
|
|
if err.Code == errInternal.Code && err.Data != nil {
|
|
if err2, ok := err.Data.(*Error); ok {
|
|
// Use alternate error when ReadResponseBody fail on other call.
|
|
return err2
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
keepData := true
|
|
errmsg := rpcerr.Error()
|
|
if s := strings.Index(errmsg, "{"); strings.HasPrefix(errmsg, "reading ") && s != -1 && strings.HasSuffix(errmsg, "}") {
|
|
// ReadResponseBody fail on this call.
|
|
errmsg = errmsg[s:]
|
|
keepData = false
|
|
}
|
|
e := &Error{}
|
|
err := json.Unmarshal([]byte(errmsg), e)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("not a jsonrpc2 error: %s (%#q)", err, rpcerr))
|
|
}
|
|
if e.Code == errInternal.Code && e.Data != nil && !keepData {
|
|
// ReadResponseBody fail on this call.
|
|
e.Data = nil
|
|
}
|
|
return e
|
|
}
|
|
|
|
// Error returns JSON representation of Error.
|
|
func (e *Error) Error() string {
|
|
buf, err := json.Marshal(e)
|
|
if err != nil {
|
|
msg, err := json.Marshal(err.Error())
|
|
if err != nil {
|
|
msg = []byte(`"` + errServerError.Message + `"`)
|
|
}
|
|
return fmt.Sprintf(`{"code":%d,"message":%s}`, errServerError.Code, string(msg))
|
|
}
|
|
return string(buf)
|
|
}
|