github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/edgemesh/pkg/protocol/http/http.go (about) 1 package http 2 3 import ( 4 "bufio" 5 "bytes" 6 "context" 7 "fmt" 8 "io" 9 "net" 10 "net/http" 11 12 "github.com/go-chassis/go-chassis/core/common" 13 "github.com/go-chassis/go-chassis/core/handler" 14 "github.com/go-chassis/go-chassis/core/invocation" 15 "k8s.io/klog" 16 17 "github.com/kubeedge/kubeedge/edgemesh/pkg/config" 18 ) 19 20 type HTTP struct { 21 Conn net.Conn 22 SvcNamespace string 23 SvcName string 24 Port int 25 26 req *http.Request 27 } 28 29 // Process handles http protocol 30 func (p *HTTP) Process() { 31 defer p.Conn.Close() 32 33 for { 34 // parse http request 35 req, err := http.ReadRequest(bufio.NewReader(p.Conn)) 36 if err != nil { 37 if err == io.EOF { 38 klog.Infof("[EdgeMesh] http client disconnected.") 39 return 40 } 41 klog.Errorf("[EdgeMesh] parse http request err: %v", err) 42 return 43 } 44 45 // http: Request.RequestURI can't be set in client requests 46 // just reset it before transport 47 req.RequestURI = "" 48 49 // create invocation 50 inv := invocation.New(context.Background()) 51 52 // set invocation 53 inv.MicroServiceName = req.Host 54 inv.SourceServiceID = "" 55 inv.Protocol = "rest" 56 inv.Strategy = config.Config.LBStrategy 57 inv.Args = req 58 inv.Reply = &http.Response{} 59 60 // create handlerchain 61 c, err := handler.CreateChain(common.Consumer, "http", handler.Loadbalance, handler.Transport) 62 if err != nil { 63 klog.Errorf("[EdgeMesh] create http handlerchain error: %v", err) 64 return 65 } 66 67 // start to handle 68 p.req = req 69 c.Next(inv, p.responseCallback) 70 } 71 } 72 73 // responseCallback implements http handlerchain callback 74 func (p *HTTP) responseCallback(data *invocation.Response) error { 75 var err error 76 var resp *http.Response 77 var respBytes []byte 78 79 // as a proxy server, make sure that edgemesh always response to a request 80 // send either the response of the real backend server or 503 back 81 if data.Err != nil { 82 klog.Errorf("[EdgeMesh] error in http handlerchain: %v", data.Err) 83 err = data.Err 84 } else { 85 if data.Result == nil { 86 klog.Errorf("[EdgeMesh] empty response from http handlerchain") 87 err = fmt.Errorf("empty response from http handlerchain") 88 } else { 89 var ok bool 90 resp, ok = data.Result.(*http.Response) 91 if !ok { 92 klog.Errorf("[EdgeMesh] http handlerchain result %+v not *http.Response type", data.Result) 93 err = fmt.Errorf("result not *http.Response type") 94 } else { 95 respBytes, err = httpResponseToBytes(resp) 96 if err != nil { 97 klog.Errorf("[EdgeMesh] convert http response to bytes err: %v", err) 98 } else { 99 // send response back 100 p.Conn.Write(respBytes) 101 return nil 102 } 103 } 104 } 105 } 106 // 503 107 resp = &http.Response{ 108 Status: fmt.Sprintf("%d %s", http.StatusServiceUnavailable, err), 109 StatusCode: http.StatusServiceUnavailable, 110 Proto: p.req.Proto, 111 Request: p.req, 112 Header: make(http.Header, 0), 113 } 114 respBytes, _ = httpResponseToBytes(resp) 115 // send error response back 116 p.Conn.Write(respBytes) 117 return err 118 } 119 120 // httpResponseToBytes transforms http.Response to bytes 121 func httpResponseToBytes(resp *http.Response) ([]byte, error) { 122 buf := new(bytes.Buffer) 123 if resp == nil { 124 return nil, fmt.Errorf("http response nil") 125 } 126 err := resp.Write(buf) 127 if err != nil { 128 return nil, err 129 } 130 return buf.Bytes(), nil 131 }