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  }