]> Cypherpunks repositories - gostls13.git/commitdiff
jsonrpc: use `error: null` for success, not `error: ""`
authorRuss Cox <rsc@golang.org>
Tue, 17 Aug 2010 22:55:42 +0000 (18:55 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 17 Aug 2010 22:55:42 +0000 (18:55 -0400)
handle missing id in server.

Fixes #1017.
Fixes #1018.

R=r
CC=golang-dev
https://golang.org/cl/1986044

src/pkg/rpc/jsonrpc/all_test.go
src/pkg/rpc/jsonrpc/client.go
src/pkg/rpc/jsonrpc/server.go

index e94c594da0b9df637e19ba6c2281f75d4e873b8e..764ee7ff36183857fa7596ef519608917c3feb3c 100644 (file)
@@ -53,7 +53,7 @@ func TestServer(t *testing.T) {
        type addResp struct {
                Id     interface{} "id"
                Result Reply       "result"
-               Error  string      "error"
+               Error  interface{} "error"
        }
 
        cli, srv := net.Pipe()
@@ -69,7 +69,7 @@ func TestServer(t *testing.T) {
                if err != nil {
                        t.Fatalf("Decode: %s", err)
                }
-               if resp.Error != "" {
+               if resp.Error != nil {
                        t.Fatalf("resp.Error: %s", resp.Error)
                }
                if resp.Id.(string) != string(i) {
@@ -79,6 +79,15 @@ func TestServer(t *testing.T) {
                        t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
                }
        }
+
+       fmt.Fprintf(cli, "{}\n")
+       var resp addResp
+       if err := dec.Decode(&resp); err != nil {
+               t.Fatalf("Decode after empty: %s", err)
+       }
+       if resp.Error == nil {
+               t.Fatalf("Expected error, got nil")
+       }
 }
 
 func TestClient(t *testing.T) {
index ed2b4ed379b3ee6b8cbd559a8ef22ab673efba6f..b34ffab056f073bae3ca55590ff5f6dd42928078 100644 (file)
@@ -7,6 +7,7 @@
 package jsonrpc
 
 import (
+       "fmt"
        "io"
        "json"
        "net"
@@ -61,13 +62,13 @@ func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) os.Error {
 type clientResponse struct {
        Id     uint64           "id"
        Result *json.RawMessage "result"
-       Error  string           "error"
+       Error  interface{}      "error"
 }
 
 func (r *clientResponse) reset() {
        r.Id = 0
        r.Result = nil
-       r.Error = ""
+       r.Error = nil
 }
 
 func (c *clientCodec) ReadResponseHeader(r *rpc.Response) os.Error {
@@ -81,8 +82,18 @@ func (c *clientCodec) ReadResponseHeader(r *rpc.Response) os.Error {
        c.pending[c.resp.Id] = "", false
        c.mutex.Unlock()
 
+       r.Error = ""
        r.Seq = c.resp.Id
-       r.Error = c.resp.Error
+       if c.resp.Error != nil {
+               x, ok := c.resp.Error.(string)
+               if !ok {
+                       return os.NewError(fmt.Sprintf("invalid error %v", c.resp.Error))
+               }
+               if x == "" {
+                       x = "unspecified error"
+               }
+               r.Error = x
+       }
        return nil
 }
 
index 9f3472a39c456bd1cc25cecb6bd9b3898475d1eb..bf53bda8daa20ccf006085643b8fbcd675b41720 100644 (file)
@@ -61,7 +61,7 @@ func (r *serverRequest) reset() {
 type serverResponse struct {
        Id     *json.RawMessage "id"
        Result interface{}      "result"
-       Error  string           "error"
+       Error  interface{}      "error"
 }
 
 func (c *serverCodec) ReadRequestHeader(r *rpc.Request) os.Error {
@@ -94,6 +94,8 @@ func (c *serverCodec) ReadRequestBody(x interface{}) os.Error {
        return json.Unmarshal(*c.req.Params, &params)
 }
 
+var null = json.RawMessage([]byte("null"))
+
 func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) os.Error {
        var resp serverResponse
        c.mutex.Lock()
@@ -105,9 +107,17 @@ func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) os.Error {
        c.pending[r.Seq] = nil, false
        c.mutex.Unlock()
 
+       if b == nil {
+               // Invalid request so no id.  Use JSON null.
+               b = &null
+       }
        resp.Id = b
        resp.Result = x
-       resp.Error = r.Error
+       if r.Error == "" {
+               resp.Error = nil
+       } else {
+               resp.Error = r.Error
+       }
        return c.enc.Encode(resp)
 }