diff --git a/docs/app-dev/subscribing-to-events-via-websocket.md b/docs/app-dev/subscribing-to-events-via-websocket.md index be35f49c..3b6db029 100644 --- a/docs/app-dev/subscribing-to-events-via-websocket.md +++ b/docs/app-dev/subscribing-to-events-via-websocket.md @@ -40,6 +40,7 @@ Response: ``` { "jsonrpc": "2.0", + "id": 0, "result": { "query": "tm.event='ValidatorSetUpdates'", "data": { diff --git a/rpc/lib/client/decode.go b/rpc/lib/client/decode.go index 0642c451..0b077f15 100644 --- a/rpc/lib/client/decode.go +++ b/rpc/lib/client/decode.go @@ -25,7 +25,7 @@ func unmarshalResponseBytes(cdc *amino.Codec, responseBytes []byte, return nil, errors.Wrap(response.Error, "response error") } - if err = assertResponseIDEqual(response, expectedID); err != nil { + if err = validateAndVerifyID(response, expectedID); err != nil { return nil, errors.Wrap(err, "error in response ID") } @@ -96,7 +96,7 @@ func validateResponseIDs(ids, expectedIDs []types.JSONRPCIntID) error { // From the JSON-RPC 2.0 spec: // id: It MUST be the same as the value of the id member in the Request Object. -func assertResponseIDEqual(res *types.RPCResponse, expectedID types.JSONRPCIntID) error { +func validateAndVerifyID(res *types.RPCResponse, expectedID types.JSONRPCIntID) error { // URIClient does not have ID in response if expectedID == -1 { return nil @@ -116,7 +116,7 @@ func validateResponseID(id interface{}) error { } _, ok := id.(types.JSONRPCIntID) if !ok { - return errors.Errorf("expected int, but got: %T", id) + return errors.Errorf("expected JSONRPCIntID, but got: %T", id) } return nil } diff --git a/rpc/lib/client/ws_client.go b/rpc/lib/client/ws_client.go index b5cd1c86..7670ac9d 100644 --- a/rpc/lib/client/ws_client.go +++ b/rpc/lib/client/ws_client.go @@ -486,13 +486,14 @@ func (c *WSClient) readRoutine() { continue } - c.mtx.RLock() + c.mtx.Lock() if _, ok := c.sentIDs[response.ID.(types.JSONRPCIntID)]; !ok { c.Logger.Error("unsolicited response ID", "id", response.ID, "expected", c.sentIDs) - c.mtx.RUnlock() + c.mtx.Unlock() continue } - c.mtx.RUnlock() + delete(c.sentIDs, response.ID.(types.JSONRPCIntID)) + c.mtx.Unlock() c.Logger.Info("got response", "id", response.ID, "result", fmt.Sprintf("%X", response.Result)) // Combine a non-blocking read on BaseService.Quit with a non-blocking write on ResponsesCh to avoid blocking diff --git a/rpc/lib/server/http_json_handler.go b/rpc/lib/server/http_json_handler.go index 8fa0fbd2..3660aa91 100644 --- a/rpc/lib/server/http_json_handler.go +++ b/rpc/lib/server/http_json_handler.go @@ -29,7 +29,7 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc, cdc *amino.Codec, logger lo WriteRPCResponseHTTP(w, types.RPCInvalidRequestError(nil, errors.Wrap(err, "error reading request body"))) return } - defer r.Body.Close() // nolint: errcheck + r.Body.Close() // nolint: errcheck // if its an empty request (like from a browser), // just display a list of functions