func (this *DynamicHandler) GetControlManager(context *web.Context) (cm *controller.ControlManager) { this.mutex.RLock() var mod, control, act string = this.module, this.controller, this.action this.mutex.RUnlock() var acterr error var action string // if mod is not found, the default mod will be used // this allows user to use shortcut path // especially when there is only one mod if s, err := context.PData.String("module"); err == nil { if this.ctrlgroup.HasModule(s) || !this.ctrlgroup.HasController(mod, s) { mod = s } else { // controller.HasController(mod, s) == true // move {action} to UPath, {controller} to {action}, {mod} to {controller} if tmpact, err := context.PData.String("action"); err == nil { lenupath := len(context.UPath) + 1 tmpupath := make(web.UPath, lenupath) tmpupath[0] = tmpact copy(tmpupath[1:lenupath], context.UPath) context.UPath = tmpupath } if tmpctrl, err := context.PData.String("controller"); err == nil { context.PData["action"] = tmpctrl } context.PData["controller"] = s context.PData["module"] = mod } } if s, err := context.PData.String("controller"); err == nil { control = s } if action, acterr = context.PData.String("action"); acterr == nil { act = action } if act == "" { act = "_" } if ctrl := this.ctrlgroup.Controller(mod, control); ctrl != nil { // allows for shortcut action to index if acterr == nil && act != "_" && !ctrl.HasAction(act) && ctrl.HasAction("index") { act = "_" lenupath := len(context.UPath) + 1 tmpupath := make(web.UPath, lenupath) tmpupath[0] = action copy(tmpupath[1:lenupath], context.UPath) context.UPath = tmpupath delete(context.PData, "action") } cm = controller.NewControlManager(context, ctrl, act) } return }
func (this *ControllerHandler) GetControlManager(context *web.Context) (cm *controller.ControlManager) { var ( act string = this.action action string acterr error ) if action, acterr = context.PData.String("action"); acterr == nil { act = action } if act == "" { act = "_" } if acterr == nil && act != "_" && !this.controlmeta.HasAction(act) && this.controlmeta.HasAction("index") { act = "_" lenupath := len(context.UPath) + 1 tmpupath := make(web.UPath, lenupath) tmpupath[0] = action copy(tmpupath[1:lenupath], context.UPath) context.UPath = tmpupath delete(context.PData, "action") } cm = controller.NewControlManager(context, this.controlmeta, act) return }
func (this *SunnyApp) ServeRequestedEndPoint(w http.ResponseWriter, r *http.Request, rep *router.RequestedEndPoint) { atomic.AddInt32(&this.runners, 1) defer this.decrunners() if atomic.LoadInt32(&this.closed) == 1 || w == nil || r == nil { return } sw := &SunnyResponseWriter{ Status: 200, ResponseWriter: w, midwares: nil, } w = sw var sunctxt *web.Context if rep == nil { goto notfound } defer func() { if err := recover(); err != nil { if re, ok := err.(web.Redirection); ok { this.triggerevent(sunctxt, "redirect", map[string]interface{}{"redirection": re}) } else if e, ok := err.(web.ContextError); ok { this.triggerevent(sunctxt, "contexterror", map[string]interface{}{"context.error": e}) handler.ErrorHtml(w, r, e.Code()) } else { log.Println(err) this.triggererror(sunctxt, err) } } if sunctxt != nil { log.Println(fmt.Sprintf("ip: %s; r: %s %s; d: %s; %d", sunctxt.RemoteAddress().String(), r.Method, r.URL.Path, time.Since(sunctxt.StartTime()).String(), w.(*SunnyResponseWriter).Status)) sunctxt.Close() } if r.MultipartForm != nil { r.MultipartForm.RemoveAll() } }() sunctxt = web.NewSunnyContext(w, r, this.id) sunctxt.Event = this.ev.NewSubRouter(event.M{"sunny.context": sunctxt}) sunctxt.UPath = rep.UPath sunctxt.PData = rep.PData sunctxt.Ext = rep.Ext sunctxt.MaxFileSize = this.MaxFileSize sunctxt.ParseRequestData() sw.ctxt = sunctxt for n, f := range this.resources { sunctxt.SetResource(n, f()) } for _, midware := range this.MiddleWares { midware.Request(sunctxt) defer midware.Cleanup(sunctxt) } if router.HandleHeaders(sunctxt, rep.EndPoint, rep.Handler) { return } sw.midwares = this.mwareresp for _, midware := range this.MiddleWares { midware.Body(sunctxt) } if ctrl, ok := rep.Handler.(controller.ControlHandler); ok { ctrlmgr := ctrl.GetControlManager(sunctxt) if ctrlmgr == nil { goto notfound } sunctxt.Module = ctrlmgr.ModuleName() sunctxt.Controller = ctrlmgr.ControllerName() sunctxt.Action = ctrlmgr.ActionName() if err := sunctxt.WaitRequestData(); err != nil { setreqerror(err, w) return } // TODO: Controller should not matter which is called first.. // make it a goroutine once determined sunctxt and ctrlmgr is completely thread-safe for _, midware := range this.MiddleWares { midware.Controller(sunctxt, ctrlmgr) } state, vw := ctrlmgr.PrepareAndExecute() defer ctrlmgr.Cleanup() if vw != nil && !sunctxt.IsRedirecting() && !sunctxt.HasError() { setFuncMap(sunctxt, vw) // TODO: View should not matter which is called first.. // make it a goroutine once determined sunctxt and ctrlmgr is completely thread-safe for _, midware := range this.MiddleWares { midware.View(sunctxt, vw) } if err := ctrlmgr.PublishView(); err != nil { log.Println(err) } } if sunctxt.HasError() { this.triggerevent(sunctxt, "contexterror", map[string]interface{}{"context.error": sunctxt.AppError()}) handler.ErrorHtml(w, r, sunctxt.ErrorCode()) } else if sunctxt.IsRedirecting() { this.triggerevent(sunctxt, "redirect", map[string]interface{}{"redirection": sunctxt.Redirection()}) } else if state != -1 && (state < 200 || state >= 300) { handler.ErrorHtml(w, r, state) } } else { if err := sunctxt.WaitRequestData(); err != nil { setreqerror(err, w) return } if h, ok := rep.Handler.(web.ContextHandler); ok { h.ServeContextHTTP(sunctxt) } else { rep.Handler.ServeHTTP(w, r) } } return notfound: handler.NotFound(w, r) }