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 }