Commit 5f573335 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Merge pull request #1894 from mslipper/bugfix/eng-1768-string-ids

go/proxyd: Allow string RPC IDs
parents d667bbb8 7b7ffd2e
---
'@eth-optimism/proxyd': minor
---
Allows string RPC ids on proxyd
...@@ -25,11 +25,6 @@ const ( ...@@ -25,11 +25,6 @@ const (
) )
var ( var (
ErrInvalidRequest = &RPCErr{
Code: -32601,
Message: "invalid request",
HTTPErrorCode: 400,
}
ErrParseErr = &RPCErr{ ErrParseErr = &RPCErr{
Code: -32700, Code: -32700,
Message: "parse error", Message: "parse error",
...@@ -67,6 +62,14 @@ var ( ...@@ -67,6 +62,14 @@ var (
} }
) )
func ErrInvalidRequest(msg string) *RPCErr {
return &RPCErr{
Code: -32601,
Message: msg,
HTTPErrorCode: 400,
}
}
type Backend struct { type Backend struct {
Name string Name string
rpcURL string rpcURL string
...@@ -498,7 +501,7 @@ func (w *WSProxier) clientPump(ctx context.Context, errC chan error) { ...@@ -498,7 +501,7 @@ func (w *WSProxier) clientPump(ctx context.Context, errC chan error) {
// just handle them here. // just handle them here.
req, err := w.prepareClientMsg(msg) req, err := w.prepareClientMsg(msg)
if err != nil { if err != nil {
var id *int var id json.RawMessage
method := MethodUnknown method := MethodUnknown
if req != nil { if req != nil {
id = req.ID id = req.ID
...@@ -555,7 +558,7 @@ func (w *WSProxier) backendPump(ctx context.Context, errC chan error) { ...@@ -555,7 +558,7 @@ func (w *WSProxier) backendPump(ctx context.Context, errC chan error) {
res, err := w.parseBackendMsg(msg) res, err := w.parseBackendMsg(msg)
if err != nil { if err != nil {
var id *int var id json.RawMessage
if res != nil { if res != nil {
id = res.ID id = res.ID
} }
......
...@@ -4,20 +4,21 @@ import ( ...@@ -4,20 +4,21 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"io/ioutil" "io/ioutil"
"strings"
) )
type RPCReq struct { type RPCReq struct {
JSONRPC string `json:"jsonrpc"` JSONRPC string `json:"jsonrpc"`
Method string `json:"method"` Method string `json:"method"`
Params json.RawMessage `json:"params"` Params json.RawMessage `json:"params"`
ID *int `json:"id"` ID json.RawMessage `json:"id"`
} }
type RPCRes struct { type RPCRes struct {
JSONRPC string `json:"jsonrpc"` JSONRPC string `json:"jsonrpc"`
Result interface{} `json:"result,omitempty"` Result interface{} `json:"result,omitempty"`
Error *RPCErr `json:"error,omitempty"` Error *RPCErr `json:"error,omitempty"`
ID *int `json:"id"` ID json.RawMessage `json:"id"`
} }
func (r *RPCRes) IsError() bool { func (r *RPCRes) IsError() bool {
...@@ -34,6 +35,17 @@ func (r *RPCErr) Error() string { ...@@ -34,6 +35,17 @@ func (r *RPCErr) Error() string {
return r.Message return r.Message
} }
func IsValidID(id json.RawMessage) bool {
// handle the case where the ID is a string
if strings.HasPrefix(string(id), "\"") && strings.HasSuffix(string(id), "\"") {
return len(id) > 2
}
// technically allows a boolean/null ID, but so does Geth
// https://github.com/ethereum/go-ethereum/blob/master/rpc/json.go#L72
return len(id) > 0 && id[0] != '{' && id[0] != '['
}
func ParseRPCReq(r io.Reader) (*RPCReq, error) { func ParseRPCReq(r io.Reader) (*RPCReq, error) {
body, err := ioutil.ReadAll(r) body, err := ioutil.ReadAll(r)
if err != nil { if err != nil {
...@@ -46,11 +58,15 @@ func ParseRPCReq(r io.Reader) (*RPCReq, error) { ...@@ -46,11 +58,15 @@ func ParseRPCReq(r io.Reader) (*RPCReq, error) {
} }
if req.JSONRPC != JSONRPCVersion { if req.JSONRPC != JSONRPCVersion {
return nil, ErrInvalidRequest return nil, ErrInvalidRequest("invalid JSON-RPC version")
} }
if req.Method == "" { if req.Method == "" {
return nil, ErrInvalidRequest return nil, ErrInvalidRequest("no method specified")
}
if !IsValidID(req.ID) {
return nil, ErrInvalidRequest("invalid ID")
} }
return req, nil return req, nil
...@@ -70,7 +86,7 @@ func ParseRPCRes(r io.Reader) (*RPCRes, error) { ...@@ -70,7 +86,7 @@ func ParseRPCRes(r io.Reader) (*RPCRes, error) {
return res, nil return res, nil
} }
func NewRPCErrorRes(id *int, err error) *RPCRes { func NewRPCErrorRes(id json.RawMessage, err error) *RPCRes {
var rpcErr *RPCErr var rpcErr *RPCErr
if rr, ok := err.(*RPCErr); ok { if rr, ok := err.(*RPCErr); ok {
rpcErr = rr rpcErr = rr
......
...@@ -232,7 +232,7 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context ...@@ -232,7 +232,7 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context
) )
} }
func writeRPCError(w http.ResponseWriter, id *int, err error) { func writeRPCError(w http.ResponseWriter, id json.RawMessage, err error) {
var res *RPCRes var res *RPCRes
if r, ok := err.(*RPCErr); ok { if r, ok := err.(*RPCErr); ok {
res = NewRPCErrorRes(id, r) res = NewRPCErrorRes(id, r)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment