github.com/turingchain2020/turingchain@v1.1.21/rpc/http.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package rpc 6 7 import ( 8 "bytes" 9 "compress/gzip" 10 "encoding/json" 11 "fmt" 12 "io" 13 "io/ioutil" 14 "net" 15 "net/http" 16 "net/rpc/jsonrpc" 17 "strings" 18 19 "github.com/rs/cors" 20 "golang.org/x/net/context" 21 "google.golang.org/grpc" 22 pr "google.golang.org/grpc/peer" 23 ) 24 25 // HTTPConn adapt HTTP connection to ReadWriteCloser 26 type HTTPConn struct { 27 r *http.Request 28 in io.Reader 29 out io.Writer 30 } 31 32 // Read rewrite the read of http 33 func (c *HTTPConn) Read(p []byte) (n int, err error) { return c.in.Read(p) } 34 35 // Write rewrite the write of http 36 func (c *HTTPConn) Write(d []byte) (n int, err error) { //添加支持gzip 发送 37 38 if strings.Contains(c.r.Header.Get("Accept-Encoding"), "gzip") { 39 gw := gzip.NewWriter(c.out) 40 defer gw.Close() 41 return gw.Write(d) 42 } 43 return c.out.Write(d) 44 } 45 46 // Close rewrite the close of http 47 func (c *HTTPConn) Close() error { return nil } 48 49 // Listen jsonsever listen 50 func (j *JSONRPCServer) Listen() (int, error) { 51 listener, err := net.Listen("tcp", rpcCfg.JrpcBindAddr) 52 if err != nil { 53 return 0, err 54 } 55 j.l = listener 56 co := cors.New(cors.Options{}) 57 58 // Insert the middleware 59 var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 60 log.Debug("JSONRPCServer", "RemoteAddr", r.RemoteAddr) 61 ip, _, err := net.SplitHostPort(r.RemoteAddr) 62 if err != nil { 63 writeError(w, r, 0, fmt.Sprintf(`The %s Address is not authorized!`, ip)) 64 return 65 } 66 67 if !checkIPWhitelist(ip) { 68 writeError(w, r, 0, fmt.Sprintf(`The %s Address is not authorized!`, ip)) 69 return 70 } 71 72 if !checkBasicAuth(r) { 73 writeError(w, r, 0, fmt.Sprintf(`Unauthozied`)) 74 return 75 } 76 if r.URL.Path == "/" { 77 data, err := ioutil.ReadAll(r.Body) 78 if err != nil { 79 writeError(w, r, 0, "Can't get request body!") 80 return 81 } 82 //格式做一个检查 83 client, err := parseJSONRpcParams(data) 84 if err != nil { 85 err = fmt.Errorf(`invalid json request err:%s`, err.Error()) 86 log.Debug("JSONRPCServer", "request", string(data), "parseErr", err) 87 writeError(w, r, 0, err.Error()) 88 return 89 } 90 funcName := strings.Split(client.Method, ".")[len(strings.Split(client.Method, "."))-1] 91 if !checkFilterPrintFuncBlacklist(funcName) { 92 log.Debug("JSONRPCServer", "request", string(data)) 93 } 94 //Release local request 95 ipaddr := net.ParseIP(ip) 96 if !ipaddr.IsLoopback() { 97 //funcName := strings.Split(client.Method, ".")[len(strings.Split(client.Method, "."))-1] 98 if checkJrpcFuncBlacklist(funcName) || !checkJrpcFuncWhitelist(funcName) { 99 writeError(w, r, client.ID, fmt.Sprintf(`The %s method is not authorized!`, funcName)) 100 return 101 } 102 } 103 serverCodec := jsonrpc.NewServerCodec(&HTTPConn{in: ioutil.NopCloser(bytes.NewReader(data)), out: w, r: r}) 104 w.Header().Set("Content-type", "application/json") 105 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 106 w.Header().Set("Content-Encoding", "gzip") 107 } 108 w.WriteHeader(200) 109 err = j.s.ServeRequest(serverCodec) 110 if err != nil { 111 log.Debug("Error while serving JSON request: %v", err) 112 return 113 } 114 } 115 }) 116 117 handler = co.Handler(handler) 118 if !rpcCfg.EnableTLS { 119 go http.Serve(listener, handler) 120 } else { 121 go http.ServeTLS(listener, handler, rpcCfg.CertFile, rpcCfg.KeyFile) 122 } 123 return listener.Addr().(*net.TCPAddr).Port, nil 124 } 125 126 type serverResponse struct { 127 ID uint64 `json:"id"` 128 Result interface{} `json:"result"` 129 Error interface{} `json:"error"` 130 } 131 132 func writeError(w http.ResponseWriter, r *http.Request, id uint64, errstr string) { 133 w.Header().Set("Content-type", "application/json") 134 //错误的请求也返回 200 135 w.WriteHeader(200) 136 resp, err := json.Marshal(&serverResponse{id, nil, errstr}) 137 if err != nil { 138 log.Debug("json marshal error, nerver happen") 139 return 140 } 141 _, err = w.Write(resp) 142 if err != nil { 143 log.Debug("Write", "err", err) 144 return 145 } 146 } 147 148 // Listen grpcserver listen 149 func (g *Grpcserver) Listen() (int, error) { 150 listener, err := net.Listen("tcp", rpcCfg.GrpcBindAddr) 151 if err != nil { 152 return 0, err 153 } 154 g.l = listener 155 go g.s.Serve(listener) 156 return listener.Addr().(*net.TCPAddr).Port, nil 157 } 158 159 func isLoopBackAddr(addr net.Addr) bool { 160 if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.IsLoopback() { 161 return true 162 } 163 return false 164 } 165 166 func auth(ctx context.Context, info *grpc.UnaryServerInfo) error { 167 getctx, ok := pr.FromContext(ctx) 168 if ok { 169 if isLoopBackAddr(getctx.Addr) { 170 return nil 171 } 172 //remoteaddr := strings.Split(getctx.Addr.String(), ":")[0] 173 ip, _, err := net.SplitHostPort(getctx.Addr.String()) 174 if err != nil { 175 return fmt.Errorf("the %s Address is not authorized", ip) 176 } 177 178 if !checkIPWhitelist(ip) { 179 return fmt.Errorf("the %s Address is not authorized", ip) 180 } 181 182 funcName := strings.Split(info.FullMethod, "/")[len(strings.Split(info.FullMethod, "/"))-1] 183 if checkGrpcFuncBlacklist(funcName) || !checkGrpcFuncWhitelist(funcName) { 184 return fmt.Errorf("the %s method is not authorized", funcName) 185 } 186 return nil 187 } 188 return fmt.Errorf("can't get remote ip") 189 } 190 191 type clientRequest struct { 192 Method string `json:"method"` 193 Params [1]interface{} `json:"params"` 194 ID uint64 `json:"id"` 195 } 196 197 func parseJSONRpcParams(data []byte) (*clientRequest, error) { 198 var req clientRequest 199 err := json.Unmarshal(data, &req) 200 if err != nil { 201 return nil, err 202 } 203 return &req, nil 204 }