From bedb715c6dbc358012457e27be9715bedfb49681 Mon Sep 17 00:00:00 2001 From: duanhf2012 Date: Sun, 5 Apr 2020 17:33:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Ehttp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/eventtype.go | 1 + example/main.go | 12 + network/http_server.go | 82 ++++++ network/tcp_msg.go | 2 +- sysservice/httpservice.go | 562 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 658 insertions(+), 1 deletion(-) create mode 100644 network/http_server.go create mode 100644 sysservice/httpservice.go diff --git a/event/eventtype.go b/event/eventtype.go index c8c5446..e6b42f6 100644 --- a/event/eventtype.go +++ b/event/eventtype.go @@ -8,6 +8,7 @@ const ( Sys_Event_Tcp_DisConnected EventType= 2 Sys_Event_Tcp_RecvPack EventType = 3 Sys_Event_Tcp_PackException EventType = 4 + Sys_Event_Http_Event EventType = 5 Sys_Event_User_Define EventType = 1000 ) diff --git a/example/main.go b/example/main.go index 48eed8f..360c648 100644 --- a/example/main.go +++ b/example/main.go @@ -125,6 +125,12 @@ type Param struct { var index int func (slf *TestServiceCall) Test(){ + //any := slf.GetProfiler().Push("xxxxxx") + //defer any.Pop() + for{ + time.Sleep(time.Second*1) + } + index += 1 //var param *Param param:=&Param{} @@ -144,6 +150,7 @@ func (slf *TestServiceCall) Test(){ func (slf *TestServiceCall) OnRelease(){ fmt.Print("OnRelease") } + func (slf *TestServiceCall) Run(){ //var ret int var input int = 10000 @@ -220,7 +227,12 @@ func (slf *TestService2) OnInit() error { return nil } + func main(){ + + //data := P{3, 4, 5, "CloudGeek"} + //buf := encode(data) + tcpService := &sysservice.TcpService{} gateService := &GateService.GateService{} tcpService.SetEventReciver(gateService) diff --git a/network/http_server.go b/network/http_server.go new file mode 100644 index 0000000..d6270a7 --- /dev/null +++ b/network/http_server.go @@ -0,0 +1,82 @@ +package network + +import ( + "crypto/tls" + "github.com/duanhf2012/origin/log" + "net/http" + "time" +) + +var Default_MaxHeaderBytes int = 1<<20 + +type CAFile struct { + Certfile string + Keyfile string +} + +type HttpServer struct { + listenAddr string + readTimeout time.Duration + writeTimeout time.Duration + + handler http.Handler + caFileList []CAFile + + httpServer *http.Server +} + +func (slf *HttpServer) Init(listenAddr string, handler http.Handler, readTimeout time.Duration, writeTimeout time.Duration) { + slf.listenAddr = listenAddr + slf.handler = handler + slf.readTimeout = readTimeout + slf.writeTimeout = writeTimeout +} + +func (slf *HttpServer) Start() { + go slf.startListen() +} + +func (slf *HttpServer) startListen() error { + var tlsCaList []tls.Certificate + var tlsConfig *tls.Config + for _, caFile := range slf.caFileList { + cer, err := tls.LoadX509KeyPair(caFile.Certfile, caFile.Keyfile) + if err != nil { + log.Fatal("Load CA [%s]-[%s] file is fail:%s", caFile.Certfile, caFile.Keyfile, err.Error()) + return err + } + tlsCaList = append(tlsCaList, cer) + } + + if len(tlsCaList) > 0 { + tlsConfig = &tls.Config{Certificates: tlsCaList} + } + + slf.httpServer = &http.Server{ + Addr: slf.listenAddr, + Handler: slf.handler, + ReadTimeout: slf.readTimeout, + WriteTimeout: slf.writeTimeout, + MaxHeaderBytes: Default_MaxHeaderBytes, + TLSConfig: tlsConfig, + } + + var err error + if len(tlsCaList) > 0 { + err = slf.httpServer.ListenAndServeTLS("", "") + } else { + err = slf.httpServer.ListenAndServe() + } + + if err != nil { + log.Fatal("Listen for address %s failure:%+v.",slf.listenAddr,err) + return err + } + + return nil +} + + +func (slf *HttpServer) SetHttps(caFile []CAFile) { + slf.caFileList = caFile +} diff --git a/network/tcp_msg.go b/network/tcp_msg.go index b47a451..a9f9361 100644 --- a/network/tcp_msg.go +++ b/network/tcp_msg.go @@ -97,7 +97,7 @@ func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) { } else if msgLen < p.minMsgLen { return nil, errors.New("message too short") } - + msgLen -= 2 // data msgData := make([]byte, msgLen) diff --git a/sysservice/httpservice.go b/sysservice/httpservice.go new file mode 100644 index 0000000..7907ae5 --- /dev/null +++ b/sysservice/httpservice.go @@ -0,0 +1,562 @@ +package sysservice + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + + "os" + "reflect" + "runtime" + "strings" + "time" + + "github.com/duanhf2012/origin/sysmodule" + + "github.com/duanhf2012/origin/rpc" + + "github.com/duanhf2012/origin/cluster" + "github.com/duanhf2012/origin/network" + "github.com/duanhf2012/origin/service" + "github.com/duanhf2012/origin/util/uuid" +) + +//http redirect +type HttpRedirectData struct { + Url string + CookieList []*http.Cookie +} + +type HttpRequest struct { + URL string + Header http.Header + Body string + + paramStr string //http://127.0.0.1:7001/aaa/bbb?aa=1 paramStr is:aa=1 + mapParam map[string]string +} + +type HttpRespone struct { + Respone []byte + RedirectData HttpRedirectData +} + +type HTTP_METHOD int + +const ( + METHOD_NONE HTTP_METHOD = iota + METHOD_GET + METHOD_POST + + METHOD_INVALID + //METHOD_PUT HTTP_METHOD = 2 +) + + +type ControllerMapsType map[string]reflect.Value +type RouterType int +const ( + FuncCall RouterType = iota+1 + StaticResource +) + +type routerMatchData struct { + callpath string + matchURL string + routerType int8 //0表示函数调用 1表示静态资源 +} + +type serveHTTPRouterMux struct { + httpFiltrateList [] HttpFiltrate + allowOrigin bool +} + +type HttpService struct { + service.Service + + httpServer network.HttpServer + controllerMaps ControllerMapsType + serverHTTPMux serveHTTPRouterMux + + postAliasUrl map[HTTP_METHOD] map[string]routerMatchData //url地址,对应本service地址 + staticRouterResource map[HTTP_METHOD] routerStaticResoutceData + + httpProcessor IHttpProcessor +} + +type routerStaticResoutceData struct { + localPath string + method HTTP_METHOD +} + + +type HttpHandle func(request *HttpRequest, resp *HttpRespone) error + +func AnalysisRouterUrl(url string) (string, error) { + + //替换所有空格 + url = strings.ReplaceAll(url, " ", "") + if len(url) <= 1 || url[0] != '/' { + return "", fmt.Errorf("url %s format is error!", url) + } + + //去掉尾部的/ + return strings.Trim(url, "/"), nil +} + +func (slf *HttpRequest) Query(key string) (string, bool) { + if slf.mapParam == nil { + slf.mapParam = make(map[string]string) + //分析字符串 + slf.paramStr = strings.Trim(slf.paramStr, "/") + paramStrList := strings.Split(slf.paramStr, "&") + for _, val := range paramStrList { + index := strings.Index(val, "=") + if index >= 0 { + slf.mapParam[val[0:index]] = val[index+1:] + } + } + } + + ret, ok := slf.mapParam[key] + return ret, ok +} + +type HttpSession struct { + request *HttpRequest + resp *HttpRespone +} + +type HttpProcessor struct { + httpSessionChan chan *HttpSession + pathRouter map[HTTP_METHOD] map[string] routerMatchData //url地址,对应本service地址 + staticRouterResource map[HTTP_METHOD] routerStaticResoutceData +} + +var Default_HttpSessionChannelNum = 100000 + +func NewHttpProcessor() *HttpProcessor{ + httpProcessor := &HttpProcessor{} + httpProcessor.httpSessionChan =make(chan *HttpSession,Default_HttpSessionChannelNum) + httpProcessor.staticRouterResource = map[HTTP_METHOD] routerStaticResoutceData{} + httpProcessor.pathRouter =map[HTTP_METHOD] map[string] routerMatchData{} + + for i:=METHOD_NONE+1;i 0 { + StrRet = fmt.Sprintf(`{"RCode": %d,"RMsg":"%s"}`, Code, Msg) + } else { + if Data == nil { + if Msg != "" { + StrRet = fmt.Sprintf(`{"RCode": 0,"RMsg":"%s"}`, Msg) + } else { + StrRet = `{"RCode": 0}` + } + } else { + if reflect.TypeOf(Data).Kind() == reflect.String { + StrRet = fmt.Sprintf(`{"RCode": %d , "Data": "%s"}`, Code, Data) + } else { + JsonRet, Err := json.Marshal(Data) + if Err != nil { + service.GetLogger().Printf(sysmodule.LEVER_ERROR, "common WriteRespone Json Marshal Err %+v", Data) + } else { + StrRet = fmt.Sprintf(`{"RCode": %d , "Data": %s}`, Code, JsonRet) + } + } + } + } + slf.Respone = []byte(StrRet) +} + +func (slf *HttpRespone) Redirect(url string, cookieList []*http.Cookie) { + slf.RedirectData.Url = url + slf.RedirectData.CookieList = cookieList +} + +func (slf *HttpRespone) redirects(w *http.ResponseWriter, req *http.Request) { + if slf.RedirectData.CookieList != nil { + for _, v := range slf.RedirectData.CookieList { + http.SetCookie(*w, v) + } + } + + http.Redirect(*w, req, slf.RedirectData.Url, + // see @andreiavrammsd comment: often 307 > 301 + http.StatusTemporaryRedirect) +}