go-eth-proxy

Transparent proxy server for eth-cache
Info | Log | Files | Refs

rpc.go (3506B)


      1 package proxy
      2 
      3 import (
      4 	"bytes"
      5 	"encoding/json"
      6 	"io"
      7 	"log"
      8 	"net/http"
      9 	"net/url"
     10 //	"strconv"
     11 
     12 	"github.com/ethereum/go-ethereum/rpc"
     13 )
     14 
     15 type jsonRpcMsg struct {
     16 	Method string
     17 
     18 }
     19 
     20 type jsonRpcError struct {
     21 	Code int
     22 }
     23 
     24 type jsonRpcResponse struct {
     25 	Error jsonRpcError
     26 }
     27 
     28 type ProxyServer struct {
     29 	*rpc.Server
     30 	uri *url.URL
     31 }
     32 
     33 type proxyWriter struct {
     34 	header map[string][]string
     35 	status int
     36 	data *bytes.Buffer
     37 	afterHeader bool
     38 }
     39 
     40 
     41 func (p *proxyWriter) Header() http.Header {
     42 	return p.header
     43 }
     44 
     45 func (p *proxyWriter) Write(b []byte) (int, error) {
     46 	log.Printf("proxyserver %s", b)
     47 	return p.data.Write(b)
     48 }
     49 
     50 func (p *proxyWriter) WriteHeader(status int) {
     51 	p.status = status
     52 
     53 }
     54 
     55 func (p *proxyWriter) Copy(w http.ResponseWriter) (int, error) {
     56 	c := 0
     57 	l := p.data.Len()
     58 	b := p.data.Bytes()
     59 	for ;c < l; {
     60 		r, err := w.Write(b[c:])
     61 		if err != nil {
     62 			return 0, err
     63 		}
     64 		c += r
     65 	}
     66 	return c, nil
     67 }
     68 
     69 func newProxyWriter() *proxyWriter {
     70 	b := make([]byte, 0, 1024)
     71 	p := &proxyWriter{
     72 		header: make(map[string][]string),
     73 		data: bytes.NewBuffer(b),
     74 	}
     75 	return p
     76 }
     77 
     78 
     79 
     80 func NewProxyServer(svc *ProxyService, remoteURI string) (*ProxyServer, error) {
     81 	var uri *url.URL
     82 	var err error
     83 
     84 	if remoteURI != "" {
     85 		uri, err = url.Parse(remoteURI)
     86 		if err != nil {
     87 			return nil, err
     88 		}
     89 	}
     90 	srv := &ProxyServer{
     91 		Server: rpc.NewServer(),
     92 		uri: uri,
     93 	}
     94 	err = srv.Server.RegisterName("eth", svc)
     95 	if err != nil {
     96 		return nil, err
     97 	}
     98 	return srv, nil
     99 }
    100 
    101 func (s *ProxyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    102 	//var rrr io.Reader
    103 	msg := jsonRpcMsg{}
    104 	b := make([]byte, r.ContentLength)
    105 	c, err := io.ReadFull(r.Body, b)
    106 	if (err != nil) {
    107 		log.Printf("%s", err)
    108 		r.Body.Close()
    109 		w.WriteHeader(http.StatusInternalServerError)
    110 		return
    111 	}
    112 	r.Body.Close()
    113 	err = json.Unmarshal(b, &msg)
    114 	if (err != nil) {
    115 		log.Printf("%s", err)
    116 		r.Body.Close()
    117 		w.WriteHeader(http.StatusInternalServerError)
    118 		return
    119 	}
    120 
    121 	rr := bytes.NewReader(b)
    122 	r.Body = io.NopCloser(rr)
    123 
    124 	for _, k := range([]string{
    125 		"eth_getTransactionByHash",
    126 	}) {
    127 		rw := newProxyWriter()
    128 		if msg.Method == k {
    129 			s.Server.ServeHTTP(rw, r)
    130 			rsp := jsonRpcResponse{}
    131 			err = json.Unmarshal(b, &rsp)
    132 			if (err != nil) {
    133 				log.Printf("%s", err)
    134 				r.Body.Close()
    135 				w.WriteHeader(http.StatusInternalServerError)
    136 				return
    137 			}
    138 			//hd := rw.Header()
    139 			//statusHd := hd["status"]
    140 			//log.Printf("got status %s from proxy", statusHd)
    141 			//if len(statusHd) > 0 && statusHd[0][:1] == "2" {
    142 			if rsp.Error.Code == 0 {
    143 //				statusCode, err := strconv.Atoi(hd["Status"][0])
    144 //				if err != nil {
    145 //					r.Body.Close()
    146 //					w.WriteHeader(http.StatusInternalServerError)
    147 //					return
    148 //				}
    149 //				rw.WriteHeader(statusCode)
    150 				rw.WriteHeader(http.StatusOK)
    151 				rw.Copy(w)
    152 				return
    153 			}
    154 
    155 			log.Printf("not found in proxy: %s", k)
    156 			rr.Seek(0, io.SeekStart)
    157 		}
    158 	}
    159 
    160 	if s.uri == nil {
    161 		log.Printf("missing remote side for unproxied method: %s", msg.Method)
    162 		w.WriteHeader(http.StatusBadGateway)
    163 		return
    164 	}
    165 
    166 	client_req := &http.Request{}
    167 	client_req.Method = "POST"
    168 	client_req.URL = s.uri
    169 	client_req.Body = r.Body
    170 	client_req.ContentLength = int64(c)
    171 	client := &http.Client{}
    172 	res, err := client.Do(client_req)
    173 	if err != nil {
    174 		log.Printf("%s", err)
    175 		r.Body.Close()
    176 		w.WriteHeader(http.StatusBadGateway)
    177 		return
    178 	}
    179 	if res.StatusCode != http.StatusOK {
    180 		v, _ := io.ReadAll(res.Body)
    181 		log.Printf("%s", v)
    182 	}
    183 	w.WriteHeader(res.StatusCode)
    184 	rrr := io.TeeReader(res.Body, w)
    185 	io.ReadAll(rrr)
    186 }