rpclib: improve errors
This commit is contained in:
parent
bed044b5a1
commit
573509b3e6
@ -64,7 +64,7 @@ func NewClient(addr string, namespace string, handler interface{}) {
|
|||||||
|
|
||||||
valOut, errOut, nout := processFuncOut(ftyp)
|
valOut, errOut, nout := processFuncOut(ftyp)
|
||||||
|
|
||||||
processResponse := func(resp clientResponse) []reflect.Value {
|
processResponse := func(resp clientResponse, code int) []reflect.Value {
|
||||||
out := make([]reflect.Value, nout)
|
out := make([]reflect.Value, nout)
|
||||||
|
|
||||||
if valOut != -1 {
|
if valOut != -1 {
|
||||||
@ -73,7 +73,7 @@ func NewClient(addr string, namespace string, handler interface{}) {
|
|||||||
if errOut != -1 {
|
if errOut != -1 {
|
||||||
out[errOut] = reflect.New(errorType).Elem()
|
out[errOut] = reflect.New(errorType).Elem()
|
||||||
if resp.Error != nil {
|
if resp.Error != nil {
|
||||||
out[errOut].Set(reflect.ValueOf(errors.New(resp.Error.Message)))
|
out[errOut].Set(reflect.ValueOf(resp.Error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,11 +139,6 @@ func NewClient(addr string, namespace string, handler interface{}) {
|
|||||||
|
|
||||||
// process response
|
// process response
|
||||||
|
|
||||||
// TODO: check error codes in spec
|
|
||||||
if httpResp.StatusCode != 200 {
|
|
||||||
return processError(errors.New("non 200 response code"))
|
|
||||||
}
|
|
||||||
|
|
||||||
var resp clientResponse
|
var resp clientResponse
|
||||||
if valOut != -1 {
|
if valOut != -1 {
|
||||||
resp.Result = result(reflect.New(ftyp.Out(valOut)))
|
resp.Result = result(reflect.New(ftyp.Out(valOut)))
|
||||||
@ -157,7 +152,7 @@ func NewClient(addr string, namespace string, handler interface{}) {
|
|||||||
return processError(errors.New("request and response id didn't match"))
|
return processError(errors.New("request and response id didn't match"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return processResponse(resp)
|
return processResponse(resp, httpResp.StatusCode)
|
||||||
})
|
})
|
||||||
|
|
||||||
val.Elem().Field(i).Set(fn)
|
val.Elem().Field(i).Set(fn)
|
||||||
|
@ -8,6 +8,14 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
rpcParseError = -32700
|
||||||
|
rpcInvalidRequest = -32600
|
||||||
|
rpcMethodNotFound = -32601
|
||||||
|
rpcInvalidParams = -32602
|
||||||
|
rpcInternalError = -32603
|
||||||
|
)
|
||||||
|
|
||||||
type rpcHandler struct {
|
type rpcHandler struct {
|
||||||
paramReceivers []reflect.Type
|
paramReceivers []reflect.Type
|
||||||
nParams int
|
nParams int
|
||||||
@ -59,6 +67,13 @@ type respError struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *respError) Error() string {
|
||||||
|
if e.Code >= -32768 && e.Code <= -32000 {
|
||||||
|
return fmt.Sprintf("RPC error (%d): %s", e.Code, e.Message)
|
||||||
|
}
|
||||||
|
return e.Message
|
||||||
|
}
|
||||||
|
|
||||||
type response struct {
|
type response struct {
|
||||||
Jsonrpc string `json:"jsonrpc"`
|
Jsonrpc string `json:"jsonrpc"`
|
||||||
Result interface{} `json:"result,omitempty"`
|
Result interface{} `json:"result,omitempty"`
|
||||||
@ -70,21 +85,18 @@ type response struct {
|
|||||||
func (s *RPCServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s *RPCServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
var req request
|
var req request
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
fmt.Println(err)
|
s.rpcError(w, &req, rpcParseError, err)
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
handler, ok := s.methods[req.Method]
|
handler, ok := s.methods[req.Method]
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Printf("rpcserver: unknown method %s\n", req.Method)
|
s.rpcError(w, &req, rpcMethodNotFound, fmt.Errorf("method '%s' not found", req.Method))
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(req.Params) != handler.nParams {
|
if len(req.Params) != handler.nParams {
|
||||||
fmt.Println("rpcserver: wrong param count")
|
s.rpcError(w, &req, rpcInvalidParams, fmt.Errorf("wrong param count"))
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,8 +109,7 @@ func (s *RPCServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
for i := 0; i < handler.nParams; i++ {
|
for i := 0; i < handler.nParams; i++ {
|
||||||
rp := reflect.New(handler.paramReceivers[i])
|
rp := reflect.New(handler.paramReceivers[i])
|
||||||
if err := json.NewDecoder(bytes.NewReader(req.Params[i].data)).Decode(rp.Interface()); err != nil {
|
if err := json.NewDecoder(bytes.NewReader(req.Params[i].data)).Decode(rp.Interface()); err != nil {
|
||||||
w.WriteHeader(500)
|
s.rpcError(w, &req, rpcParseError, err)
|
||||||
fmt.Println(err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,11 +141,28 @@ func (s *RPCServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *RPCServer) rpcError(w http.ResponseWriter, req *request, code int, err error) {
|
||||||
|
w.WriteHeader(500)
|
||||||
|
if req.Id == nil { // notification
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := response{
|
||||||
|
Jsonrpc: "2.0",
|
||||||
|
Id: *req.Id,
|
||||||
|
Error: &respError{
|
||||||
|
Code: code,
|
||||||
|
Message: err.(error).Error(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = json.NewEncoder(w).Encode(resp)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *RPCServer) Register(namespace string, r interface{}) {
|
func (s *RPCServer) Register(namespace string, r interface{}) {
|
||||||
val := reflect.ValueOf(r)
|
val := reflect.ValueOf(r)
|
||||||
//TODO: expect ptr
|
//TODO: expect ptr
|
||||||
@ -198,3 +226,5 @@ func processFuncOut(funcType reflect.Type) (valOut int, errOut int, n int) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ error = &respError{}
|
||||||
|
@ -87,7 +87,7 @@ func TestRPC(t *testing.T) {
|
|||||||
t.Fatal("expected error")
|
t.Fatal("expected error")
|
||||||
}
|
}
|
||||||
if err.Error() != "test" {
|
if err.Error() != "test" {
|
||||||
t.Fatal("wrong error")
|
t.Fatal("wrong error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddGet(int) int
|
// AddGet(int) int
|
||||||
@ -151,8 +151,8 @@ func TestRPC(t *testing.T) {
|
|||||||
NewClient(testServ.URL, "SimpleServerHandler", &erronly)
|
NewClient(testServ.URL, "SimpleServerHandler", &erronly)
|
||||||
|
|
||||||
_, err = erronly.AddGet()
|
_, err = erronly.AddGet()
|
||||||
if err == nil || err.Error() != "RPC client error: non 200 response code" {
|
if err == nil || err.Error() != "RPC error (-32602): wrong param count" {
|
||||||
t.Error("wrong error")
|
t.Error("wrong error:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var wrongtype struct {
|
var wrongtype struct {
|
||||||
@ -161,8 +161,18 @@ func TestRPC(t *testing.T) {
|
|||||||
NewClient(testServ.URL, "SimpleServerHandler", &wrongtype)
|
NewClient(testServ.URL, "SimpleServerHandler", &wrongtype)
|
||||||
|
|
||||||
err = wrongtype.Add("not an int")
|
err = wrongtype.Add("not an int")
|
||||||
if err == nil || err.Error() != "RPC client error: non 200 response code" {
|
if err == nil || err.Error() != "RPC error (-32700): json: cannot unmarshal string into Go value of type int" {
|
||||||
t.Error("wrong error")
|
t.Error("wrong error:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var notfound struct {
|
||||||
|
NotThere func(string) error
|
||||||
|
}
|
||||||
|
NewClient(testServ.URL, "SimpleServerHandler", ¬found)
|
||||||
|
|
||||||
|
err = notfound.NotThere("hello?")
|
||||||
|
if err == nil || err.Error() != "RPC error (-32601): method 'SimpleServerHandler.NotThere' not found" {
|
||||||
|
t.Error("wrong error:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user