From f2eda1c635b31304ea5fe85fc711cdb7cf919494 Mon Sep 17 00:00:00 2001 From: duanhf2012 Date: Tue, 7 Apr 2020 19:33:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4httpservice=E4=B8=8Eexample?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cluster/parsecfg.go | 24 +- event/event.go | 21 +- example/GateService/GateService.go | 15 + example/config/cluster/subnet/cluster.json | 2 +- example/config/cluster/subnet/service.json | 14 +- example/main.go | 5 +- network/http_server.go | 2 +- node/node.go | 12 +- service/service.go | 1 + sysservice/httpservice.go | 802 ++++++++++----------- 10 files changed, 438 insertions(+), 460 deletions(-) diff --git a/cluster/parsecfg.go b/cluster/parsecfg.go index 0d827b9..856dff2 100644 --- a/cluster/parsecfg.go +++ b/cluster/parsecfg.go @@ -42,20 +42,21 @@ func (slf *Cluster) ReadAllSubNetConfig() error { clusterCfgPath :=strings.TrimRight(configdir,"/") +"/cluster" fileInfoList,err := ioutil.ReadDir(clusterCfgPath) if err != nil { - return err + return fmt.Errorf("Read dir %s is fail :%+v",clusterCfgPath,err) } + slf.mapSubNetInfo =map[string] SubNet{} for _,f := range fileInfoList{ if f.IsDir() == true { - subnetinfo,err:=slf.ReadClusterConfig(strings.TrimRight(strings.TrimRight(clusterCfgPath,"/"),"\\")+"/"+f.Name()+"/"+"cluster.json") + filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath,"/"),"\\")+"/"+f.Name()+"/"+"cluster.json" + subnetinfo,err:=slf.ReadClusterConfig(filePath) if err != nil { - return err + return fmt.Errorf("read file path %s is error:%+v" ,filePath,err) } slf.mapSubNetInfo[f.Name()] = *subnetinfo } } - return nil } @@ -63,14 +64,16 @@ func (slf *Cluster) ReadLocalSubNetServiceConfig(subnet string) error { clusterCfgPath :=strings.TrimRight(configdir,"/") +"/cluster" fileInfoList,err := ioutil.ReadDir(clusterCfgPath) if err != nil { - return err + return fmt.Errorf("Read %s dir is fail:%+v ",clusterCfgPath,err) } + slf.mapSubNetInfo =map[string] SubNet{} for _,f := range fileInfoList{ if f.IsDir() == true && f.Name()==subnet{ //同一子网 - localNodeServiceCfg,err:=slf.ReadServiceConfig(strings.TrimRight(strings.TrimRight(clusterCfgPath,"/"),"\\")+"/"+f.Name()+"/"+"service.json") + filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath,"/"),"\\")+"/"+f.Name()+"/"+"service.json" + localNodeServiceCfg,err:=slf.ReadServiceConfig(filePath) if err != nil { - return err + return fmt.Errorf("Read file %s is fail :%+v",filePath,err) } slf.localNodeServiceCfg =localNodeServiceCfg } @@ -89,8 +92,10 @@ func (slf *Cluster) InitCfg(currentNodeId int) error{ localNodeMapService := map[string]interface{}{} //本Node支持的服务 localNodeInfo := NodeInfo{} - err := slf.ReadAllSubNetConfig() + if err != nil { + return err + } //分析配置 var localSubnetName string @@ -160,8 +165,7 @@ func (slf *Cluster) InitCfg(currentNodeId int) error{ slf.localNodeInfo =localNodeInfo //读取服务 - slf.ReadLocalSubNetServiceConfig(slf.localsubnet.SubNetName) - return err + return slf.ReadLocalSubNetServiceConfig(slf.localsubnet.SubNetName) } diff --git a/event/event.go b/event/event.go index a7b99eb..26f699f 100644 --- a/event/event.go +++ b/event/event.go @@ -81,6 +81,9 @@ func (slf *EventProcessor) GetEventReciver() IEventProcessor{ return slf.eventReciver } +type IHttpEventData interface { + Handle() +} func (slf *EventProcessor) EventHandler(processor IEventProcessor,ev *Event) { defer func() { @@ -92,5 +95,21 @@ func (slf *EventProcessor) EventHandler(processor IEventProcessor,ev *Event) { } }() + if slf.innerEventHandler(ev) == true { + return + } + processor.OnEventHandler(ev) -} \ No newline at end of file +} + +func (slf *EventProcessor) innerEventHandler(ev *Event) bool { + switch ev.Type { + case Sys_Event_Http_Event: + ev.Data.(IHttpEventData).Handle() + return true + } + + return false +} + + diff --git a/example/GateService/GateService.go b/example/GateService/GateService.go index ad79bca..393977b 100644 --- a/example/GateService/GateService.go +++ b/example/GateService/GateService.go @@ -13,15 +13,30 @@ import ( type GateService struct { service.Service processor network.Processor + httpRouter sysservice.IHttpRouter } func (slf *GateService) OnInit() error{ tcpervice := node.GetService("TcpService").(*sysservice.TcpService) slf.processor = &processor.PBProcessor{} tcpervice.SetProcessor(slf.processor) + + httpervice := node.GetService("HttpService").(*sysservice.HttpService) + slf.httpRouter = sysservice.NewHttpHttpRouter(slf) + httpervice.SetHttpRouter(slf.httpRouter) + + slf.httpRouter.RegRouter(sysservice.METHOD_GET,"/get/query",slf.HttpTest) + slf.httpRouter.SetServeFile(sysservice.METHOD_GET,"/img/head/","d:/img") return nil } +func (slf *GateService) HttpTest(session *sysservice.HttpSession) { + session.SetHeader("a","b") + session.Write([]byte("this is a test")) + v,_:=session.Query("a") + v2,_:=session.Query("b") + fmt.Print(string(session.GetBody()),"\n",v,"\n",v2) +} func (slf *GateService) OnEventHandler(ev *event.Event) error{ if ev.Type == event.Sys_Event_Tcp_RecvPack { diff --git a/example/config/cluster/subnet/cluster.json b/example/config/cluster/subnet/cluster.json index 1b5d92e..c51337c 100644 --- a/example/config/cluster/subnet/cluster.json +++ b/example/config/cluster/subnet/cluster.json @@ -5,7 +5,7 @@ "ListenAddr":"127.0.0.1:8001", "NodeName": "Node_Test1", "remark":"//以_打头的,表示只在本机进程,不对整个子网开发", - "ServiceList": ["TestService1","TestService2","TestServiceCall","GateService","TcpService"] + "ServiceList": ["TestService1","TestService2","TestServiceCall","GateService","TcpService","HttpService"] } ] } \ No newline at end of file diff --git a/example/config/cluster/subnet/service.json b/example/config/cluster/subnet/service.json index 1a7666a..c76c7e3 100644 --- a/example/config/cluster/subnet/service.json +++ b/example/config/cluster/subnet/service.json @@ -1,6 +1,16 @@ { - "HttpService":{ - "Port":10001 + "HttpService":{ + "ListenAddr":"0.0.0.0:9402", + "ReadTimeout":10000, + "WriteTimeout":10000, + "ProcessTimeout":10000, + "CAFile":[ + { + "Certfile":"", + "Keyfile":"" + } + ] + }, "TcpService":{ "ListenAddr":"0.0.0.0:9030", diff --git a/example/main.go b/example/main.go index 360c648..15ede55 100644 --- a/example/main.go +++ b/example/main.go @@ -236,7 +236,10 @@ func main(){ tcpService := &sysservice.TcpService{} gateService := &GateService.GateService{} tcpService.SetEventReciver(gateService) - node.Setup(tcpService,gateService) + + httpService := &sysservice.HttpService{} + + node.Setup(tcpService,gateService,httpService) node.OpenProfilerReport(time.Second*10) node.Start() } diff --git a/network/http_server.go b/network/http_server.go index d6270a7..7c525f5 100644 --- a/network/http_server.go +++ b/network/http_server.go @@ -77,6 +77,6 @@ func (slf *HttpServer) startListen() error { } -func (slf *HttpServer) SetHttps(caFile []CAFile) { +func (slf *HttpServer) SetCAFile(caFile []CAFile) { slf.caFileList = caFile } diff --git a/node/node.go b/node/node.go index 961658b..2256298 100644 --- a/node/node.go +++ b/node/node.go @@ -68,22 +68,26 @@ func initNode(id int){ //1.初始化集群 err := cluster.GetCluster().Init(GetNodeId()) if err != nil { - panic(err) + log.Fatal("read system config is error %+v",err) } //2.service模块初始化 service.Init(closeSig) - //3.初始化预安装的服务 + //3.setup service for _,s := range preSetupService { - pServiceCfg := cluster.GetCluster().GetServiceCfg(s.GetName()) - s.Init(s,cluster.GetRpcClient,cluster.GetRpcServer,pServiceCfg) //是否配置的service if cluster.GetCluster().IsConfigService(s.GetName()) == false { continue } service.Setup(s) } + + //4.init service + for _,s := range preSetupService { + pServiceCfg := cluster.GetCluster().GetServiceCfg(s.GetName()) + s.Init(s,cluster.GetRpcClient,cluster.GetRpcServer,pServiceCfg) + } } func Start() { diff --git a/service/service.go b/service/service.go index a8d2dbd..db8ab8c 100644 --- a/service/service.go +++ b/service/service.go @@ -195,3 +195,4 @@ func (slf *Service) GetProfiler() *profiler.Profiler{ return slf.profiler } + diff --git a/sysservice/httpservice.go b/sysservice/httpservice.go index 7907ae5..07adb7f 100644 --- a/sysservice/httpservice.go +++ b/sysservice/httpservice.go @@ -1,49 +1,31 @@ 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/event" "github.com/duanhf2012/origin/network" "github.com/duanhf2012/origin/service" "github.com/duanhf2012/origin/util/uuid" + "io" + "io/ioutil" + "net/http" + "os" + "strings" + "time" ) +var Default_ReadTimeout time.Duration = time.Second*10 +var Default_WriteTimeout time.Duration = time.Second*10 +var Default_ProcessTimeout time.Duration = time.Second*10 + +var Default_HttpRouter *HttpRouter= &HttpRouter{} + //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 ( @@ -52,67 +34,95 @@ const ( 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 HttpHandle func(session *HttpSession) type routerMatchData struct { - callpath string matchURL string - routerType int8 //0表示函数调用 1表示静态资源 + httpHandle HttpHandle } -type serveHTTPRouterMux struct { - httpFiltrateList [] HttpFiltrate - allowOrigin bool + +type routerServeFileData struct { + matchUrl string + localPath string + method HTTP_METHOD } +type IHttpRouter interface { + RegRouter(method HTTP_METHOD, url string, handle HttpHandle) bool + Router(session *HttpSession) + + PutHttpSession(httpSession *HttpSession) + SetServeFile(method HTTP_METHOD, urlpath string, dirname string) error + SetFormFileKey(formFileKey string) + GetFormFileKey()string +} + + +type HttpRouter struct { + pathRouter map[HTTP_METHOD] map[string] routerMatchData //url地址,对应本service地址 + serveFileData map[string] *routerServeFileData + eventReciver event.IEventProcessor + httpFiltrateList [] HttpFiltrate + + formFileKey string +} + +type HttpSession struct { + httpRouter IHttpRouter + r *http.Request + w http.ResponseWriter + + //parse result + mapParam map[string]string + body []byte + + //processor result + statusCode int + msg []byte + fileData *routerServeFileData + redirectData *HttpRedirectData + sessionDone chan *HttpSession +} + + 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 + httpRouter IHttpRouter + listenAddr string + allowOrigin bool + processTimeout time.Duration } -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) +func NewHttpHttpRouter(eventReciver event.IEventProcessor) IHttpRouter { + httpRouter := &HttpRouter{} + httpRouter.eventReciver = eventReciver + httpRouter.pathRouter =map[HTTP_METHOD] map[string] routerMatchData{} + httpRouter.serveFileData = map[string] *routerServeFileData{} + httpRouter.formFileKey = "file" + 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.httpRouter.PutHttpSession(session) + ticker := time.NewTicker(slf.processTimeout) + select { + case <-ticker.C: + session.WriteStatusCode(http.StatusGatewayTimeout) + session.flush() + break + case <- session.sessionDone: + if session.fileData!=nil { + slf.ProcessFile(session) + }else if session.redirectData!=nil { + session.redirects() + }else{ + session.flush() } } - 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) -} +} \ No newline at end of file