good morning!!!!

Skip to content
Snippets Groups Projects
Commit 8fd243ee authored by Taylor Gerring's avatar Taylor Gerring
Browse files

Add JSON RPC batch support

parent fe819f3b
No related branches found
No related tags found
No related merge requests found
package rpc
import (
"encoding/json"
"io/ioutil"
"net/http"
"github.com/ethereum/go-ethereum/logger"
......@@ -16,54 +18,71 @@ const (
// JSONRPC returns a handler that implements the Ethereum JSON-RPC API.
func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
var json JsonWrapper
var jsw JsonWrapper
api := NewEthereumApi(pipe, dataDir)
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// TODO this needs to be configurable
w.Header().Set("Access-Control-Allow-Origin", "*")
rpchttplogger.DebugDetailln("Handling request")
// Limit request size to resist DoS
if req.ContentLength > maxSizeReqLength {
jsonerr := &RpcErrorObject{-32700, "Request too large"}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
jsw.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
return
}
reqParsed, reqerr := json.ParseRequestBody(req)
switch reqerr.(type) {
case nil:
break
case *DecodeParamError, *InsufficientParamsError, *ValidationError:
jsonerr := &RpcErrorObject{-32602, reqerr.Error()}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
return
default:
jsonerr := &RpcErrorObject{-32700, "Could not parse request"}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
return
defer req.Body.Close()
body, err := ioutil.ReadAll(req.Body)
if err != nil {
jsonerr := &RpcErrorObject{-32700, "Could not read request body"}
jsw.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
}
var response interface{}
reserr := api.GetRequestReply(&reqParsed, &response)
switch reserr.(type) {
case nil:
break
case *NotImplementedError:
jsonerr := &RpcErrorObject{-32601, reserr.Error()}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Error: jsonerr})
// Try to parse the request as a single
var reqSingle RpcRequest
if err := json.Unmarshal(body, &reqSingle); err == nil {
response := RpcResponse(api, &reqSingle)
jsw.Send(w, &response)
return
case *DecodeParamError, *InsufficientParamsError, *ValidationError:
jsonerr := &RpcErrorObject{-32602, reserr.Error()}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Error: jsonerr})
return
default:
jsonerr := &RpcErrorObject{-32603, reserr.Error()}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Error: jsonerr})
}
// Try to parse the request to batch
var reqBatch []RpcRequest
if err := json.Unmarshal(body, &reqBatch); err == nil {
// Build response batch
resBatch := make([]*interface{}, len(reqBatch))
for i, request := range reqBatch {
response := RpcResponse(api, &request)
resBatch[i] = response
}
jsw.Send(w, resBatch)
return
}
rpchttplogger.DebugDetailf("Generated response: %T %s", response, response)
json.Send(w, &RpcSuccessResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Result: response})
// Not a batch or single request, error
jsonerr := &RpcErrorObject{-32600, "Could not decode request"}
jsw.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
})
}
func RpcResponse(api *EthereumApi, request *RpcRequest) *interface{} {
var reply, response interface{}
reserr := api.GetRequestReply(request, &reply)
switch reserr.(type) {
case nil:
response = &RpcSuccessResponse{JsonRpc: jsonrpcver, ID: request.ID, Result: reply}
case *NotImplementedError:
jsonerr := &RpcErrorObject{-32601, reserr.Error()}
response = &RpcErrorResponse{JsonRpc: jsonrpcver, ID: request.ID, Error: jsonerr}
case *DecodeParamError, *InsufficientParamsError, *ValidationError:
jsonerr := &RpcErrorObject{-32602, reserr.Error()}
response = &RpcErrorResponse{JsonRpc: jsonrpcver, ID: request.ID, Error: jsonerr}
default:
jsonerr := &RpcErrorObject{-32603, reserr.Error()}
response = &RpcErrorResponse{JsonRpc: jsonrpcver, ID: request.ID, Error: jsonerr}
}
rpchttplogger.DebugDetailf("Generated response: %T %s", response, response)
return &response
}
......@@ -21,7 +21,7 @@ import (
"fmt"
"io"
"math/big"
"net/http"
// "net/http"
"reflect"
"time"
......@@ -106,24 +106,6 @@ func (self JsonWrapper) Send(writer io.Writer, v interface{}) (n int, err error)
return writer.Write(payload)
}
func (self JsonWrapper) ParseRequestBody(req *http.Request) (RpcRequest, error) {
var reqParsed RpcRequest
// Convert JSON to native types
d := json.NewDecoder(req.Body)
defer req.Body.Close()
err := d.Decode(&reqParsed)
if err != nil {
rpclogger.Errorln("Error decoding JSON: ", err)
return reqParsed, err
}
rpclogger.DebugDetailf("Parsed request: %s", reqParsed)
return reqParsed, nil
}
func toHex(b []byte) string {
hex := common.Bytes2Hex(b)
// Prefer output of "0x0" instead of "0x"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment