diff --git a/jsonrpc/codec.go b/jsonrpc/codec.go index 7cbe7c1f5f..f8f5191f9a 100644 --- a/jsonrpc/codec.go +++ b/jsonrpc/codec.go @@ -15,6 +15,8 @@ type Request struct { Params json.RawMessage `json:"params,omitempty"` } +type BatchRequest []Request + // Response is a jsonrpc response interface type Response interface { GetID() interface{} diff --git a/jsonrpc/dispatcher.go b/jsonrpc/dispatcher.go index ae7ef31668..a324214529 100644 --- a/jsonrpc/dispatcher.go +++ b/jsonrpc/dispatcher.go @@ -231,11 +231,45 @@ func (d *Dispatcher) RemoveFilterByWs(conn wsConn) { } func (d *Dispatcher) HandleWs(reqBody []byte, conn wsConn) ([]byte, error) { + // first try to unmarshal to batch request + // if there is an error try to unmarshal to single request + var batchReq BatchRequest + if err := json.Unmarshal(reqBody, &batchReq); err == nil { + const ( + openSquareBracket = 91 // [ + closeSquareBracket = 93 // ] + comma = 44 // , + ) + + result := []byte{openSquareBracket} + + for i, req := range batchReq { + bytes, err := d.handleWs(req, conn) + if err != nil { + return nil, err + } + + if i > 0 { + result = append(result, comma) + } + + result = append(result, bytes...) + } + + // batch output should look like + // [ { "requestId": "1", "status": 200 }, { "requestId": "2", "status": 200 } ] + return append(result, closeSquareBracket), nil + } + var req Request if err := json.Unmarshal(reqBody, &req); err != nil { return NewRPCResponse(req.ID, "2.0", nil, NewInvalidRequestError("Invalid json request")).Bytes() } + return d.handleWs(req, conn) +} + +func (d *Dispatcher) handleWs(req Request, conn wsConn) ([]byte, error) { // if the request method is eth_subscribe we need to create a // new filter with ws connection if req.Method == "eth_subscribe" {