diff --git a/context.go b/context.go new file mode 100644 index 0000000..7923b6c --- /dev/null +++ b/context.go @@ -0,0 +1,71 @@ +package f5 + +import ( + "net/http" + "q5" +) + +type Context struct { + s *HttpServer + w *http.ResponseWriter + r *http.Request + c *middleware + l *q5.ListHead + aborted bool + suspended bool +} + +func (this *Context) do() { + this.l.ForEach( + func(data interface{}) bool { + m := data.(*middleware) + this.c = m + m.handlerFunc(this) + return !this.aborted && !this.suspended + }) +} + +func (this *Context) Next() { + this.suspended = true + this.l.ForEachFrom(this.c.entry.Next(), + func(data interface{}) bool { + m := data.(*middleware) + this.c = m + m.handlerFunc(this) + return !this.aborted + }) +} + +func (this *Context) Abort() { + this.aborted = true +} + +func (this *Context) Request(name string) *q5.XValue { + return q5.Request(this.r, name) +} + +func (this *Context) Header(name string) string { + return "" +} + +func (this *Context) Response(data string) { + q5.Response(this.w, data) +} + +func (this *Context)ResponseErr(errCode int32, errMsg string) { + respObj := q5.NewMxoObject() + respObj.SetXValue("errcode", q5.NewXInt32(errCode)) + respObj.SetXValue("errmsg", q5.NewXString(errMsg)) + q5.Response(this.w, respObj.ToJsonStr()) +} + +func (this *Context) ResponseOk() { + q5.ResponseOk(this.w) +} + +func (this *Context) Set(key string, val interface{}) { +} + +func (this *Context) Get(key string) interface{} { + return nil +} diff --git a/httpserver.go b/httpserver.go index c28c8c7..e24af6c 100644 --- a/httpserver.go +++ b/httpserver.go @@ -13,17 +13,26 @@ type HttpServer struct { okTimes int64 pageNotFoundTimes int64 maxHandleTime int64 + startTimes int64 handlersMutex sync.RWMutex - handlers map[string]func(*http.ResponseWriter, *http.Request) + handlers map[string]HandlerFunc + + restHandlersMutex sync.RWMutex + restHandlers map[string]*q5.ListHead + + globalMiddlewareMutex sync.RWMutex + globalMiddlewareList q5.ListHead } func (this *HttpServer) Init(serviceName string, logOutputTime int32) *HttpServer { - this.handlers = make(map[string]func(*http.ResponseWriter, *http.Request)) - http.HandleFunc("/webapp/index.php", this.dispatchRequest) + this.handlers = make(map[string]HandlerFunc) + this.restHandlers = make(map[string]*q5.ListHead) + this.globalMiddlewareList.Init(nil) + this.RegisterRestHandle("/webapp/index", this.dispatchRequest) this.RegisterHandle("Ops", "selfChecking", - func (w* http.ResponseWriter, r *http.Request) { - (*w).Write([]byte(`{"errcode":0, "errmsg":"", "healthy":1, "max_rundelay":10}`)) + func (c *Context) { + c.Response(`{"errcode":0, "errmsg":"", "healthy":1, "max_rundelay":10}`) }) SysLog().Info("HttpServer.Init") if logOutputTime > 0 { @@ -52,29 +61,31 @@ func (this *HttpServer) UnInit() { } func (this *HttpServer) Start(listen_port int32) { + atomic.AddInt64(&this.totalRequestTimes, 1) + this.installGlobalMiddleware() SysLog().Info("HttpServer.Start listen_port:%d", listen_port) go http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", listen_port), nil) } -func (this *HttpServer) dispatchRequest(w http.ResponseWriter, r *http.Request) { +func (this *HttpServer) dispatchRequest(c *Context) { atomic.AddInt64(&this.totalRequestTimes, 1) - handleName := q5.Request(r, "c").GetString() + "$" + q5.Request(r, "a").GetString() + handleName := c.Request("c").GetString() + "$" + c.Request("a").GetString() handle := this.getHandle(handleName) if handle != nil { beginTick := q5.GetTickCount() - handle(&w, r) + handle(c) endTick := q5.GetTickCount() if oldVal := atomic.LoadInt64(&this.maxHandleTime); beginTick - endTick > oldVal { atomic.CompareAndSwapInt64(&this.maxHandleTime, oldVal, endTick - beginTick) } atomic.AddInt64(&this.okTimes, 1) } else { - w.Write([]byte(`{"errcode":404, "errmsg":"接口不存在"}`)) + c.Response(`{"errcode":404, "errmsg":"接口不存在"}`) atomic.AddInt64(&this.pageNotFoundTimes, 1) } } -func (this *HttpServer) getHandle(handleName string) (func(*http.ResponseWriter, *http.Request)) { +func (this *HttpServer) getHandle(handleName string) HandlerFunc { this.handlersMutex.Lock() defer this.handlersMutex.Unlock() if handle, ok := this.handlers[handleName]; ok { @@ -84,8 +95,7 @@ func (this *HttpServer) getHandle(handleName string) (func(*http.ResponseWriter, } } -func (this *HttpServer) RegisterHandle(c string, a string, - handle func(*http.ResponseWriter, *http.Request)) { +func (this *HttpServer) RegisterHandle(c string, a string, handle HandlerFunc) { this.handlersMutex.Lock() defer this.handlersMutex.Unlock() handleName := c + "$" + a @@ -93,9 +103,63 @@ func (this *HttpServer) RegisterHandle(c string, a string, } func (this *HttpServer) RegisterRestHandle(pattern string, - handle func(*http.ResponseWriter, *http.Request)) { - http.HandleFunc(pattern, - func (w http.ResponseWriter, r *http.Request) { - handle(&w, r) - }) + handle HandlerFunc) { + if this.totalRequestTimes > 0 { + panic("") + } + this.restHandlersMutex.Lock() + defer this.restHandlersMutex.Unlock() + + p := new(middleware) + p.entry.Init(nil) + p.handlerFunc = handle + if l, ok := this.restHandlers[pattern]; ok { + l.AddTail(&p.entry) + } else { + l := q5.MakeListHead() + l.AddTail(&p.entry) + this.restHandlers[pattern] = l + http.HandleFunc(pattern, + func (w http.ResponseWriter, r *http.Request) { + c := new(Context) + c.s = this + c.w = &w + c.r = r + c.l = l + c.do() + }) + } +} + +func (this *HttpServer) Use(handle HandlerFunc) { + if this.totalRequestTimes > 0 { + panic("") + } + this.globalMiddlewareMutex.Lock() + defer this.globalMiddlewareMutex.Unlock() + + p := new(middleware) + p.entry.Init(nil) + p.handlerFunc = handle + this.globalMiddlewareList.AddTail(&p.entry) +} + +func (this *HttpServer) installGlobalMiddleware() { + this.restHandlersMutex.Lock() + this.globalMiddlewareMutex.Lock() + defer this.restHandlersMutex.Unlock() + defer this.globalMiddlewareMutex.Unlock() + + /*for key, val := range this.restHandlers { + + }*/ +} + +func (this *HttpServer) UseGroupBegin(groupNames ...string) { +} + +func (this *HttpServer) UseGroupEnd() { +} + +func (this *HttpServer) DefineGroup(groupName string, handlers ...HandlerFunc) { } diff --git a/types.go b/types.go index 1673529..4f65803 100644 --- a/types.go +++ b/types.go @@ -11,3 +11,11 @@ type IMMsgNode struct { params *q5.XParams next *IMMsgNode } + +type HandlerFunc func(*Context) + +type middleware struct { + middlewareType int32 + handlerFunc HandlerFunc + entry q5.ListHead +}