c3bc2bed by astaxie

add methodName to fix #380 & arrangement the router

1 parent 7b27b7fe
...@@ -29,21 +29,22 @@ var ( ...@@ -29,21 +29,22 @@ var (
29 ) 29 )
30 30
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 TplNames string 35 actionName string
36 Layout string 36 TplNames string
37 TplExt string 37 Layout string
38 _xsrf_token string 38 TplExt string
39 gotofunc string 39 _xsrf_token string
40 CruSession session.SessionStore 40 gotofunc string
41 XSRFExpire int 41 CruSession session.SessionStore
42 AppController interface{} 42 XSRFExpire int
43 AppController interface{}
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,15 +594,64 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -591,15 +594,64 @@ 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
599 context.Input.Params = params
600 runMethod = p.getRunMethod(r.Method, route)
596 break 601 break
597 } 602 }
598 } 603 }
599 604
600 context.Input.Params = params 605 if !findrouter && p.enableAuto {
606 // deal with url with diffirent ext
607 // /controller/simple
608 // /controller/simple.html
609 // /controller/simple.json
610 // /controller/simple.rss
611 lastindex := strings.LastIndex(requestPath, "/")
612 lastsub := requestPath[lastindex+1:]
613 if subindex := strings.LastIndex(lastsub, "."); subindex != -1 {
614 context.Input.Params[":ext"] = lastsub[subindex+1:]
615 r.URL.Query().Add(":ext", lastsub[subindex+1:])
616 r.URL.RawQuery = r.URL.Query().Encode()
617 requestPath = requestPath[:len(requestPath)-len(lastsub[subindex:])]
618 }
619 for cName, methodmap := range p.autoRouter {
620 // if prev already find the router break
621 if findrouter {
622 break
623 }
624 if strings.ToLower(requestPath) == "/"+cName {
625 http.Redirect(w, r, requestPath+"/", 301)
626 goto Admin
627 }
628 // if there's no action, set the default action to index
629 if strings.ToLower(requestPath) == "/"+cName+"/" {
630 requestPath = requestPath + "index"
631 }
632 // if the request path start with controllerName
633 if strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/") {
634 for mName, controllerType := range methodmap {
635 if strings.ToLower(requestPath) == "/"+cName+"/"+strings.ToLower(mName) ||
636 (strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/"+strings.ToLower(mName)) &&
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 }
601 647
602 if runrouter != nil { 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 {
603 if r.Method == "POST" { 655 if r.Method == "POST" {
604 r.ParseMultipartForm(MaxMemory) 656 r.ParseMultipartForm(MaxMemory)
605 } 657 }
...@@ -609,14 +661,15 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -609,14 +661,15 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
609 } 661 }
610 662
611 //Invoke the request handler 663 //Invoke the request handler
612 vc := reflect.New(runrouter.controllerType) 664 vc := reflect.New(runrouter)
613 665
614 //call the controller init function 666 //call the controller init function
615 method := vc.MethodByName("Init") 667 method := vc.MethodByName("Init")
616 in := make([]reflect.Value, 3) 668 in := make([]reflect.Value, 4)
617 in[0] = reflect.ValueOf(context) 669 in[0] = reflect.ValueOf(context)
618 in[1] = reflect.ValueOf(runrouter.controllerType.Name()) 670 in[1] = reflect.ValueOf(runrouter.Name())
619 in[2] = reflect.ValueOf(vc.Interface()) 671 in[2] = reflect.ValueOf(runMethod)
672 in[3] = reflect.ValueOf(vc.Interface())
620 method.Call(in) 673 method.Call(in)
621 674
622 //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
...@@ -636,110 +689,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -636,110 +689,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
636 method = vc.MethodByName("Prepare") 689 method = vc.MethodByName("Prepare")
637 method.Call(in) 690 method.Call(in)
638 691
639 //if response has written,yes don't run next
640 if !w.started { 692 if !w.started {
641 if r.Method == "GET" { 693 //exec main logic
642 if runrouter.hasMethod { 694 method = vc.MethodByName(runMethod)
643 if m, ok := runrouter.methods["get"]; ok { 695 method.Call(in)
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 696
667 method.Call(in) 697 //render template
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() { 698 if !w.started && !context.Input.IsWebsocket() {
744 if AutoRender { 699 if AutoRender {
745 method = vc.MethodByName("Render") 700 method = vc.MethodByName("Render")
...@@ -748,6 +703,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -748,6 +703,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
748 } 703 }
749 } 704 }
750 705
706 // finish all runrouter. release resource
751 method = vc.MethodByName("Finish") 707 method = vc.MethodByName("Finish")
752 method.Call(in) 708 method.Call(in)
753 709
...@@ -757,105 +713,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -757,105 +713,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
757 } 713 }
758 } 714 }
759 715
760 //start autorouter
761
762 if p.enableAuto {
763 if !findrouter {
764 lastindex := strings.LastIndex(requestPath, "/")
765 lastsub := requestPath[lastindex+1:]
766 if subindex := strings.LastIndex(lastsub, "."); subindex != -1 {
767 context.Input.Params[":ext"] = lastsub[subindex+1:]
768 r.URL.Query().Add(":ext", lastsub[subindex+1:])
769 r.URL.RawQuery = r.URL.Query().Encode()
770 requestPath = requestPath[:len(requestPath)-len(lastsub[subindex:])]
771 }
772 for cName, methodmap := range p.autoRouter {
773
774 if strings.ToLower(requestPath) == "/"+cName {
775 http.Redirect(w, r, requestPath+"/", 301)
776 goto Admin
777 }
778
779 if strings.ToLower(requestPath) == "/"+cName+"/" {
780 requestPath = requestPath + "index"
781 }
782 if strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/") {
783 for mName, controllerType := range methodmap {
784 if strings.ToLower(requestPath) == "/"+cName+"/"+strings.ToLower(mName) ||
785 (strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/"+strings.ToLower(mName)) &&
786 requestPath[len("/"+cName+"/"+strings.ToLower(mName)):len("/"+cName+"/"+strings.ToLower(mName))+1] == "/") {
787 if r.Method == "POST" {
788 r.ParseMultipartForm(MaxMemory)
789 }
790 // set find
791 findrouter = true
792
793 //execute middleware filters
794 if do_filter(BeforeExec) {
795 goto Admin
796 }
797
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
807 vc := reflect.New(controllerType)
808
809 //call the controller init function
810 init := vc.MethodByName("Init")
811 in := make([]reflect.Value, 3)
812 in[0] = reflect.ValueOf(context)
813 in[1] = reflect.ValueOf(controllerType.Name())
814 in[2] = reflect.ValueOf(vc.Interface())
815 init.Call(in)
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)
822 //if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf
823 if EnableXSRF {
824 method = vc.MethodByName("XsrfToken")
825 method.Call(in)
826 if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" ||
827 (r.Method == "POST" && (r.Form.Get("_method") == "delete" || r.Form.Get("_method") == "put")) {
828 method = vc.MethodByName("CheckXsrfCookie")
829 method.Call(in)
830 }
831 }
832 if !w.started && !context.Input.IsWebsocket() {
833 if AutoRender {
834 method = vc.MethodByName("Render")
835 callMethodWithError(method, in)
836 }
837 }
838 method = vc.MethodByName("Finish")
839 method.Call(in)
840
841 //execute middleware filters
842 if do_filter(AfterExec) {
843 goto Admin
844 }
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 }
858
859 Admin: 716 Admin:
860 do_filter(FinishRouter) 717 do_filter(FinishRouter)
861 718
...@@ -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!