c3bc2bed by astaxie

add methodName to fix #380 & arrangement the router

1 parent 7b27b7fe
...@@ -31,7 +31,8 @@ var ( ...@@ -31,7 +31,8 @@ var (
31 type Controller struct { 31 type Controller struct {
32 Ctx *context.Context 32 Ctx *context.Context
33 Data map[interface{}]interface{} 33 Data map[interface{}]interface{}
34 ChildName string 34 controllerName string
35 actionName string
35 TplNames string 36 TplNames string
36 Layout string 37 Layout string
37 TplExt string 38 TplExt string
...@@ -43,7 +44,7 @@ type Controller struct { ...@@ -43,7 +44,7 @@ type Controller struct {
43 } 44 }
44 45
45 type ControllerInterface interface { 46 type ControllerInterface interface {
46 Init(ct *context.Context, childName string, app interface{}) 47 Init(ct *context.Context, controllerName, actionName string, app interface{})
47 Prepare() 48 Prepare()
48 Get() 49 Get()
49 Post() 50 Post()
...@@ -56,11 +57,12 @@ type ControllerInterface interface { ...@@ -56,11 +57,12 @@ type ControllerInterface interface {
56 Render() error 57 Render() error
57 } 58 }
58 59
59 func (c *Controller) Init(ctx *context.Context, childName string, app interface{}) { 60 func (c *Controller) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
60 c.Data = make(map[interface{}]interface{}) 61 c.Data = make(map[interface{}]interface{})
61 c.Layout = "" 62 c.Layout = ""
62 c.TplNames = "" 63 c.TplNames = ""
63 c.ChildName = childName 64 c.controllerName = controllerName
65 c.actionName = actionName
64 c.Ctx = ctx 66 c.Ctx = ctx
65 c.TplExt = "tpl" 67 c.TplExt = "tpl"
66 c.AppController = app 68 c.AppController = app
...@@ -123,7 +125,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { ...@@ -123,7 +125,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
123 //if the controller has set layout, then first get the tplname's content set the content to the layout 125 //if the controller has set layout, then first get the tplname's content set the content to the layout
124 if c.Layout != "" { 126 if c.Layout != "" {
125 if c.TplNames == "" { 127 if c.TplNames == "" {
126 c.TplNames = c.ChildName + "/" + strings.ToLower(c.Ctx.Request.Method) + "." + c.TplExt 128 c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
127 } 129 }
128 if RunMode == "dev" { 130 if RunMode == "dev" {
129 BuildTemplate(ViewsPath) 131 BuildTemplate(ViewsPath)
...@@ -150,7 +152,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { ...@@ -150,7 +152,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
150 return icontent, nil 152 return icontent, nil
151 } else { 153 } else {
152 if c.TplNames == "" { 154 if c.TplNames == "" {
153 c.TplNames = c.ChildName + "/" + strings.ToLower(c.Ctx.Request.Method) + "." + c.TplExt 155 c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
154 } 156 }
155 if RunMode == "dev" { 157 if RunMode == "dev" {
156 BuildTemplate(ViewsPath) 158 BuildTemplate(ViewsPath)
......
...@@ -211,6 +211,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM ...@@ -211,6 +211,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
211 } 211 }
212 } 212 }
213 213
214 // add auto router to controller
214 func (p *ControllerRegistor) AddAuto(c ControllerInterface) { 215 func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
215 p.enableAuto = true 216 p.enableAuto = true
216 reflectVal := reflect.ValueOf(c) 217 reflectVal := reflect.ValueOf(c)
...@@ -424,8 +425,9 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -424,8 +425,9 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
424 425
425 starttime := time.Now() 426 starttime := time.Now()
426 requestPath := r.URL.Path 427 requestPath := r.URL.Path
427 var runrouter *controllerInfo 428 var runrouter reflect.Type
428 var findrouter bool 429 var findrouter bool
430 var runMethod string
429 params := make(map[string]string) 431 params := make(map[string]string)
430 432
431 w := &responseWriter{writer: rw} 433 w := &responseWriter{writer: rw}
...@@ -550,8 +552,9 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -550,8 +552,9 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
550 for _, route := range p.fixrouters { 552 for _, route := range p.fixrouters {
551 n := len(requestPath) 553 n := len(requestPath)
552 if requestPath == route.pattern { 554 if requestPath == route.pattern {
553 runrouter = route 555 runrouter = route.controllerType
554 findrouter = true 556 findrouter = true
557 runMethod = p.getRunMethod(r.Method, route)
555 break 558 break
556 } 559 }
557 // pattern /admin url /admin 200 /admin/ 404 560 // pattern /admin url /admin 200 /admin/ 404
...@@ -591,176 +594,20 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -591,176 +594,20 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
591 //reassemble query params and add to RawQuery 594 //reassemble query params and add to RawQuery
592 r.URL.RawQuery = url.Values(values).Encode() 595 r.URL.RawQuery = url.Values(values).Encode()
593 } 596 }
594 runrouter = route 597 runrouter = route.controllerType
595 findrouter = true 598 findrouter = true
596 break
597 }
598 }
599
600 context.Input.Params = params 599 context.Input.Params = params
601 600 runMethod = p.getRunMethod(r.Method, route)
602 if runrouter != nil { 601 break
603 if r.Method == "POST" {
604 r.ParseMultipartForm(MaxMemory)
605 }
606 //execute middleware filters
607 if do_filter(BeforeExec) {
608 goto Admin
609 }
610
611 //Invoke the request handler
612 vc := reflect.New(runrouter.controllerType)
613
614 //call the controller init function
615 method := vc.MethodByName("Init")
616 in := make([]reflect.Value, 3)
617 in[0] = reflect.ValueOf(context)
618 in[1] = reflect.ValueOf(runrouter.controllerType.Name())
619 in[2] = reflect.ValueOf(vc.Interface())
620 method.Call(in)
621
622 //if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf
623 if EnableXSRF {
624 in = make([]reflect.Value, 0)
625 method = vc.MethodByName("XsrfToken")
626 method.Call(in)
627 if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" ||
628 (r.Method == "POST" && (r.Form.Get("_method") == "delete" || r.Form.Get("_method") == "put")) {
629 method = vc.MethodByName("CheckXsrfCookie")
630 method.Call(in)
631 }
632 }
633
634 //call prepare function
635 in = make([]reflect.Value, 0)
636 method = vc.MethodByName("Prepare")
637 method.Call(in)
638
639 //if response has written,yes don't run next
640 if !w.started {
641 if r.Method == "GET" {
642 if runrouter.hasMethod {
643 if m, ok := runrouter.methods["get"]; ok {
644 method = vc.MethodByName(m)
645 } else if m, ok = runrouter.methods["*"]; ok {
646 method = vc.MethodByName(m)
647 } else {
648 method = vc.MethodByName("Get")
649 }
650 } else {
651 method = vc.MethodByName("Get")
652 }
653 method.Call(in)
654 } else if r.Method == "HEAD" {
655 if runrouter.hasMethod {
656 if m, ok := runrouter.methods["head"]; ok {
657 method = vc.MethodByName(m)
658 } else if m, ok = runrouter.methods["*"]; ok {
659 method = vc.MethodByName(m)
660 } else {
661 method = vc.MethodByName("Head")
662 }
663 } else {
664 method = vc.MethodByName("Head")
665 }
666
667 method.Call(in)
668 } else if r.Method == "DELETE" || (r.Method == "POST" && r.Form.Get("_method") == "delete") {
669 if runrouter.hasMethod {
670 if m, ok := runrouter.methods["delete"]; ok {
671 method = vc.MethodByName(m)
672 } else if m, ok = runrouter.methods["*"]; ok {
673 method = vc.MethodByName(m)
674 } else {
675 method = vc.MethodByName("Delete")
676 }
677 } else {
678 method = vc.MethodByName("Delete")
679 }
680 method.Call(in)
681 } else if r.Method == "PUT" || (r.Method == "POST" && r.Form.Get("_method") == "put") {
682 if runrouter.hasMethod {
683 if m, ok := runrouter.methods["put"]; ok {
684 method = vc.MethodByName(m)
685 } else if m, ok = runrouter.methods["*"]; ok {
686 method = vc.MethodByName(m)
687 } else {
688 method = vc.MethodByName("Put")
689 }
690 } else {
691 method = vc.MethodByName("Put")
692 }
693 method.Call(in)
694 } else if r.Method == "POST" {
695 if runrouter.hasMethod {
696 if m, ok := runrouter.methods["post"]; ok {
697 method = vc.MethodByName(m)
698 } else if m, ok = runrouter.methods["*"]; ok {
699 method = vc.MethodByName(m)
700 } else {
701 method = vc.MethodByName("Post")
702 }
703 } else {
704 method = vc.MethodByName("Post")
705 }
706 method.Call(in)
707 } else if r.Method == "PATCH" {
708 if runrouter.hasMethod {
709 if m, ok := runrouter.methods["patch"]; ok {
710 method = vc.MethodByName(m)
711 } else if m, ok = runrouter.methods["*"]; ok {
712 method = vc.MethodByName(m)
713 } else {
714 method = vc.MethodByName("Patch")
715 }
716 } else {
717 method = vc.MethodByName("Patch")
718 }
719 method.Call(in)
720 } else if r.Method == "OPTIONS" {
721 if runrouter.hasMethod {
722 if m, ok := runrouter.methods["options"]; ok {
723 method = vc.MethodByName(m)
724 } else if m, ok = runrouter.methods["*"]; ok {
725 method = vc.MethodByName(m)
726 } else {
727 method = vc.MethodByName("Options")
728 }
729 } else {
730 method = vc.MethodByName("Options")
731 }
732 method.Call(in)
733 }
734 gotofunc := vc.Elem().FieldByName("gotofunc").String()
735 if gotofunc != "" {
736 method = vc.MethodByName(gotofunc)
737 if method.IsValid() {
738 method.Call(in)
739 } else {
740 panic("gotofunc is exists:" + gotofunc)
741 }
742 }
743 if !w.started && !context.Input.IsWebsocket() {
744 if AutoRender {
745 method = vc.MethodByName("Render")
746 callMethodWithError(method, in)
747 }
748 }
749 }
750
751 method = vc.MethodByName("Finish")
752 method.Call(in)
753
754 //execute middleware filters
755 if do_filter(AfterExec) {
756 goto Admin
757 } 602 }
758 } 603 }
759 604
760 //start autorouter 605 if !findrouter && p.enableAuto {
761 606 // deal with url with diffirent ext
762 if p.enableAuto { 607 // /controller/simple
763 if !findrouter { 608 // /controller/simple.html
609 // /controller/simple.json
610 // /controller/simple.rss
764 lastindex := strings.LastIndex(requestPath, "/") 611 lastindex := strings.LastIndex(requestPath, "/")
765 lastsub := requestPath[lastindex+1:] 612 lastsub := requestPath[lastindex+1:]
766 if subindex := strings.LastIndex(lastsub, "."); subindex != -1 { 613 if subindex := strings.LastIndex(lastsub, "."); subindex != -1 {
...@@ -770,57 +617,64 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -770,57 +617,64 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
770 requestPath = requestPath[:len(requestPath)-len(lastsub[subindex:])] 617 requestPath = requestPath[:len(requestPath)-len(lastsub[subindex:])]
771 } 618 }
772 for cName, methodmap := range p.autoRouter { 619 for cName, methodmap := range p.autoRouter {
773 620 // if prev already find the router break
621 if findrouter {
622 break
623 }
774 if strings.ToLower(requestPath) == "/"+cName { 624 if strings.ToLower(requestPath) == "/"+cName {
775 http.Redirect(w, r, requestPath+"/", 301) 625 http.Redirect(w, r, requestPath+"/", 301)
776 goto Admin 626 goto Admin
777 } 627 }
778 628 // if there's no action, set the default action to index
779 if strings.ToLower(requestPath) == "/"+cName+"/" { 629 if strings.ToLower(requestPath) == "/"+cName+"/" {
780 requestPath = requestPath + "index" 630 requestPath = requestPath + "index"
781 } 631 }
632 // if the request path start with controllerName
782 if strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/") { 633 if strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/") {
783 for mName, controllerType := range methodmap { 634 for mName, controllerType := range methodmap {
784 if strings.ToLower(requestPath) == "/"+cName+"/"+strings.ToLower(mName) || 635 if strings.ToLower(requestPath) == "/"+cName+"/"+strings.ToLower(mName) ||
785 (strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/"+strings.ToLower(mName)) && 636 (strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/"+strings.ToLower(mName)) &&
786 requestPath[len("/"+cName+"/"+strings.ToLower(mName)):len("/"+cName+"/"+strings.ToLower(mName))+1] == "/") { 637 requestPath[len("/"+cName+"/"+strings.ToLower(mName)):len("/"+cName+"/"+strings.ToLower(mName))+1] == "/") {
638 runrouter = controllerType
639 runMethod = mName
640 findrouter = true
641 break
642 }
643 }
644 }
645 }
646 }
647
648 //if no matches to url, throw a not found exception
649 if !findrouter {
650 middleware.Exception("404", rw, r, "")
651 goto Admin
652 }
653
654 if findrouter {
787 if r.Method == "POST" { 655 if r.Method == "POST" {
788 r.ParseMultipartForm(MaxMemory) 656 r.ParseMultipartForm(MaxMemory)
789 } 657 }
790 // set find
791 findrouter = true
792
793 //execute middleware filters 658 //execute middleware filters
794 if do_filter(BeforeExec) { 659 if do_filter(BeforeExec) {
795 goto Admin 660 goto Admin
796 } 661 }
797 662
798 //parse params
799 otherurl := requestPath[len("/"+cName+"/"+strings.ToLower(mName)):]
800 if len(otherurl) > 1 {
801 plist := strings.Split(otherurl, "/")
802 for k, v := range plist[1:] {
803 params[strconv.Itoa(k)] = v
804 }
805 }
806 //Invoke the request handler 663 //Invoke the request handler
807 vc := reflect.New(controllerType) 664 vc := reflect.New(runrouter)
808 665
809 //call the controller init function 666 //call the controller init function
810 init := vc.MethodByName("Init") 667 method := vc.MethodByName("Init")
811 in := make([]reflect.Value, 3) 668 in := make([]reflect.Value, 4)
812 in[0] = reflect.ValueOf(context) 669 in[0] = reflect.ValueOf(context)
813 in[1] = reflect.ValueOf(controllerType.Name()) 670 in[1] = reflect.ValueOf(runrouter.Name())
814 in[2] = reflect.ValueOf(vc.Interface()) 671 in[2] = reflect.ValueOf(runMethod)
815 init.Call(in) 672 in[3] = reflect.ValueOf(vc.Interface())
816 //call prepare function
817 in = make([]reflect.Value, 0)
818 method := vc.MethodByName("Prepare")
819 method.Call(in)
820 method = vc.MethodByName(mName)
821 method.Call(in) 673 method.Call(in)
674
822 //if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf 675 //if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf
823 if EnableXSRF { 676 if EnableXSRF {
677 in = make([]reflect.Value, 0)
824 method = vc.MethodByName("XsrfToken") 678 method = vc.MethodByName("XsrfToken")
825 method.Call(in) 679 method.Call(in)
826 if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" || 680 if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" ||
...@@ -829,12 +683,27 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -829,12 +683,27 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
829 method.Call(in) 683 method.Call(in)
830 } 684 }
831 } 685 }
686
687 //call prepare function
688 in = make([]reflect.Value, 0)
689 method = vc.MethodByName("Prepare")
690 method.Call(in)
691
692 if !w.started {
693 //exec main logic
694 method = vc.MethodByName(runMethod)
695 method.Call(in)
696
697 //render template
832 if !w.started && !context.Input.IsWebsocket() { 698 if !w.started && !context.Input.IsWebsocket() {
833 if AutoRender { 699 if AutoRender {
834 method = vc.MethodByName("Render") 700 method = vc.MethodByName("Render")
835 callMethodWithError(method, in) 701 callMethodWithError(method, in)
836 } 702 }
837 } 703 }
704 }
705
706 // finish all runrouter. release resource
838 method = vc.MethodByName("Finish") 707 method = vc.MethodByName("Finish")
839 method.Call(in) 708 method.Call(in)
840 709
...@@ -842,18 +711,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -842,18 +711,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
842 if do_filter(AfterExec) { 711 if do_filter(AfterExec) {
843 goto Admin 712 goto Admin
844 } 713 }
845
846 goto Admin
847 }
848 }
849 }
850 }
851 }
852 }
853
854 //if no matches to url, throw a not found exception
855 if !findrouter {
856 middleware.Exception("404", rw, r, "")
857 } 714 }
858 715
859 Admin: 716 Admin:
...@@ -864,7 +721,7 @@ Admin: ...@@ -864,7 +721,7 @@ Admin:
864 timeend := time.Since(starttime) 721 timeend := time.Since(starttime)
865 if FilterMonitorFunc(r.Method, requestPath, timeend) { 722 if FilterMonitorFunc(r.Method, requestPath, timeend) {
866 if runrouter != nil { 723 if runrouter != nil {
867 go toolbox.StatisticsMap.AddStatistics(r.Method, requestPath, runrouter.controllerType.Name(), timeend) 724 go toolbox.StatisticsMap.AddStatistics(r.Method, requestPath, runrouter.Name(), timeend)
868 } else { 725 } else {
869 go toolbox.StatisticsMap.AddStatistics(r.Method, requestPath, "", timeend) 726 go toolbox.StatisticsMap.AddStatistics(r.Method, requestPath, "", timeend)
870 } 727 }
...@@ -890,6 +747,21 @@ func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.Resp ...@@ -890,6 +747,21 @@ func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.Resp
890 return handler 747 return handler
891 } 748 }
892 749
750 func (p *ControllerRegistor) getRunMethod(method string, router *controllerInfo) string {
751 method = strings.ToLower(method)
752 if router.hasMethod {
753 if m, ok := router.methods[method]; ok {
754 return m
755 } else if m, ok = router.methods["*"]; ok {
756 return m
757 } else {
758 return strings.Title(method)
759 }
760 } else {
761 return strings.Title(method)
762 }
763 }
764
893 //responseWriter is a wrapper for the http.ResponseWriter 765 //responseWriter is a wrapper for the http.ResponseWriter
894 //started set to true if response was written to then don't execute other handler 766 //started set to true if response was written to then don't execute other handler
895 type responseWriter struct { 767 type responseWriter struct {
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!