Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions endpointproxy/neonproxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package endpointproxy

import (
"bytes"
"compress/gzip"
"encoding/json"
"io/ioutil"
"net/http"
"net/http/httputil"
"net/url"

"github.com/celer-network/goutils/log"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
)

const (
neonHeaderRpcMethod = "header-rpc-method"
)

type NeonProxy struct {
neonTargetUrl *url.URL
}

// NewProxy takes target host and creates a reverse proxy
func (c *NeonProxy) startNeonProxy(targetHost string, port int) error {
var err error
c.neonTargetUrl, err = url.Parse(targetHost)
if err != nil {
return err
}
p := httputil.NewSingleHostReverseProxy(c.neonTargetUrl)
originalDirector := p.Director
p.Director = func(req *http.Request) {
originalDirector(req)
c.modifyNeonRequest(req)
}
p.ModifyResponse = modifyNeonResponse()
mux := http.NewServeMux()
mux.HandleFunc("/", proxyRequestHandler(p))
go startCustomProxyByPort(port, mux)
return nil
}

func (c *NeonProxy) modifyNeonRequest(req *http.Request) {
req.URL.Scheme = c.neonTargetUrl.Scheme
req.URL.Host = c.neonTargetUrl.Host
req.Host = c.neonTargetUrl.Host
reqStr, err := ioutil.ReadAll(req.Body)
if err != nil {
log.Warnf("invalid neon request err:%s", err.Error())
return
}
var msg jsonrpcMessage
if err = json.Unmarshal(reqStr, &msg); err != nil {
log.Warnf("fail to unmarshal this neon req body err:%s", err.Error())
return
}
req.Header.Set(neonHeaderRpcMethod, msg.Method)
req.Body = ioutil.NopCloser(bytes.NewReader(reqStr))
}

func modifyNeonResponse() func(*http.Response) error {
return func(resp *http.Response) error {
if resp.Request != nil && resp.Request.Header.Get(neonHeaderRpcMethod) == MethodEthGetBlockByNumber {
gzipReader, err := gzip.NewReader(resp.Body)
if err != nil {
return err
}
originData, err := ioutil.ReadAll(gzipReader)
if err != nil {
return err
}
var msg jsonrpcMessage
if err = json.Unmarshal(originData, &msg); err != nil {
return err
}
var result Header
if err = json.Unmarshal(msg.Result, &result); err != nil {
return err
}
if result.UncleHash == nil {
result.UncleHash = &types.EmptyUncleHash
}
if result.Difficulty == nil {
result.Difficulty = &hexutil.Big{}
}
if result.GasLimit == nil {
result.GasLimit = new(hexutil.Uint64)
}
msg.Result, err = json.Marshal(result)
if err != nil {
return err
}
newData, err := json.Marshal(msg)
if err != nil {
return err
}
var b bytes.Buffer
gz := gzip.NewWriter(&b)
if _, err = gz.Write(newData); err != nil {
return err
}
if err = gz.Close(); err != nil {
return err
}
resp.Body = ioutil.NopCloser(bytes.NewReader(b.Bytes()))
resp.ContentLength = int64(len(b.Bytes()))
}
return nil
}
}
5 changes: 5 additions & 0 deletions endpointproxy/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const (

sxChainId = 416
sxTestnetChainId = 647

neonTestnetChainId = 245022926
)

// this struct is copied from eth client, so we need to pay attention to the update of eth client
Expand All @@ -62,6 +64,9 @@ type jsonError struct {
func StartProxy(originEndpoint string, chainId uint64, port int) error {
var err error
switch chainId {
case neonTestnetChainId:
h := new(NeonProxy)
err = h.startNeonProxy(originEndpoint, port)
case sxChainId, sxTestnetChainId:
h := new(SxProxy)
err = h.startSxProxy(originEndpoint, port)
Expand Down