From 2dee30183d3cb8a9a3a869a8a907d391bd877767 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 28 May 2013 13:58:42 +0800 Subject: [PATCH 1/4] add structmap function for controller --- router.go | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/router.go b/router.go index 97de5317..58df660a 100644 --- a/router.go +++ b/router.go @@ -1,12 +1,14 @@ package beego import ( + "errors" "fmt" "net/http" "net/url" "reflect" "regexp" "runtime" + "strconv" "strings" ) @@ -183,6 +185,69 @@ func (p *ControllerRegistor) FilterPrefixPath(path string, filter http.HandlerFu }) } +func structMap(vc reflect.Value, params *map[string]string) error { + for k, v := range *params { + names := strings.Split(k, ".") + var value reflect.Value = vc + for i, name := range names { + if i != len(names)-1 { + if value.Kind() != reflect.Struct { + return errors.New("arg error") + } + value := value.FieldByName(name) + if !value.IsValid() { + return errors.New("arg error") + } + } else { + tv := value.FieldByName(name) + fmt.Println(name, tv, tv.Kind()) + if !tv.IsValid() { + return errors.New("arg error") + } + if !tv.CanSet() { + return errors.New("can not set " + name) + } + var l interface{} + switch k := tv.Kind(); k { + case reflect.String: + l = v + case reflect.Bool: + l = (v == "true") + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: + x, err := strconv.Atoi(v) + if err != nil { + return errors.New("arg " + v + " as int: " + err.Error()) + } + l = x + case reflect.Int64: + x, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return errors.New("arg " + v + " as int: " + err.Error()) + } + l = x + case reflect.Float32, reflect.Float64: + x, err := strconv.ParseFloat(v, 64) + if err != nil { + return errors.New("arg " + v + " as float64: " + err.Error()) + } + l = x + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + x, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return errors.New("arg " + v + " as int: " + err.Error()) + } + l = x + case reflect.Struct: + fmt.Println("can not set an struct") + } + + tv.Set(reflect.ValueOf(l)) + } + } + } + return nil +} + // AutoRoute func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) { defer func() { @@ -351,6 +416,9 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) init := vc.MethodByName("Init") in := make([]reflect.Value, 2) ct := &Context{ResponseWriter: w, Request: r, Params: params} + + structMap(vc.Elem(), ¶ms) + in[0] = reflect.ValueOf(ct) in[1] = reflect.ValueOf(runrouter.controllerType.Name()) init.Call(in) From 8b7cba037e72510de83d44e2c5a22b1df7704e72 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 28 May 2013 16:43:23 +0800 Subject: [PATCH 2/4] add url params -> controller's member feature --- router.go | 61 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/router.go b/router.go index 58df660a..a60330b3 100644 --- a/router.go +++ b/router.go @@ -1,7 +1,6 @@ package beego import ( - "errors" "fmt" "net/http" "net/url" @@ -12,6 +11,10 @@ import ( "strings" ) +var ( + sc *Controller = &Controller{} +) + type controllerInfo struct { pattern string regex *regexp.Regexp @@ -46,7 +49,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface) { if strings.HasPrefix(part, ":") { expr := "(.+)" //a user may choose to override the defult expression - // similar to expressjs: ‘/user/:id([0-9]+)’ + // similar to expressjs: ‘/user/:id([0-9]+)’ if index := strings.Index(part, "("); index != -1 { expr = part[index:] part = part[:index] @@ -120,7 +123,7 @@ func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) { if strings.HasPrefix(part, ":") { expr := "([^/]+)" //a user may choose to override the defult expression - // similar to expressjs: ‘/user/:id([0-9]+)’ + // similar to expressjs: ‘/user/:id([0-9]+)’ if index := strings.Index(part, "("); index != -1 { expr = part[index:] part = part[:index] @@ -185,27 +188,40 @@ func (p *ControllerRegistor) FilterPrefixPath(path string, filter http.HandlerFu }) } -func structMap(vc reflect.Value, params *map[string]string) error { - for k, v := range *params { +func StructMap(vc reflect.Value, params *url.Values) error { + + for k, t := range *params { + v := t[0] names := strings.Split(k, ".") var value reflect.Value = vc for i, name := range names { - if i != len(names)-1 { - if value.Kind() != reflect.Struct { - return errors.New("arg error") + name = strings.Title(name) + if i == 0 { + if reflect.ValueOf(sc).Elem().FieldByName(name).IsValid() { + Trace("Controller's property should not be changed by mapper.") + break } - value := value.FieldByName(name) + } + if value.Kind() != reflect.Struct { + Trace(fmt.Sprintf("arg error, value kind is %v", value.Kind())) + break + } + + if i != len(names)-1 { + value = value.FieldByName(name) if !value.IsValid() { - return errors.New("arg error") + Trace(fmt.Sprintf("(%v value is not valid %v)", name, value)) + break } } else { tv := value.FieldByName(name) - fmt.Println(name, tv, tv.Kind()) if !tv.IsValid() { - return errors.New("arg error") + Trace(fmt.Sprintf("struct %v has no field named %v", value, name)) + break } if !tv.CanSet() { - return errors.New("can not set " + name) + Trace("can not set " + k) + break } var l interface{} switch k := tv.Kind(); k { @@ -216,29 +232,33 @@ func structMap(vc reflect.Value, params *map[string]string) error { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: x, err := strconv.Atoi(v) if err != nil { - return errors.New("arg " + v + " as int: " + err.Error()) + Trace("arg " + v + " as int: " + err.Error()) + break } l = x case reflect.Int64: x, err := strconv.ParseInt(v, 10, 64) if err != nil { - return errors.New("arg " + v + " as int: " + err.Error()) + Trace("arg " + v + " as int: " + err.Error()) + break } l = x case reflect.Float32, reflect.Float64: x, err := strconv.ParseFloat(v, 64) if err != nil { - return errors.New("arg " + v + " as float64: " + err.Error()) + Trace("arg " + v + " as float64: " + err.Error()) + break } l = x case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: x, err := strconv.ParseUint(v, 10, 64) if err != nil { - return errors.New("arg " + v + " as int: " + err.Error()) + Trace("arg " + v + " as int: " + err.Error()) + break } l = x case reflect.Struct: - fmt.Println("can not set an struct") + Trace("can not set an struct") } tv.Set(reflect.ValueOf(l)) @@ -412,13 +432,14 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) //Invoke the request handler vc := reflect.New(runrouter.controllerType) + r.ParseForm() + StructMap(vc.Elem(), &r.Form) + //call the controller init function init := vc.MethodByName("Init") in := make([]reflect.Value, 2) ct := &Context{ResponseWriter: w, Request: r, Params: params} - structMap(vc.Elem(), ¶ms) - in[0] = reflect.ValueOf(ct) in[1] = reflect.ValueOf(runrouter.controllerType.Name()) init.Call(in) From 65041aae713e40a487e866e047bf5a5896892352 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 31 May 2013 14:07:06 +0800 Subject: [PATCH 3/4] remove nonuse parseForm and change the StructMap's params --- router.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/router.go b/router.go index a60330b3..fe5373e1 100644 --- a/router.go +++ b/router.go @@ -188,9 +188,8 @@ func (p *ControllerRegistor) FilterPrefixPath(path string, filter http.HandlerFu }) } -func StructMap(vc reflect.Value, params *url.Values) error { - - for k, t := range *params { +func StructMap(vc reflect.Value, r *http.Request) error { + for k, t := range r.Form { v := t[0] names := strings.Split(k, ".") var value reflect.Value = vc @@ -432,8 +431,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) //Invoke the request handler vc := reflect.New(runrouter.controllerType) - r.ParseForm() - StructMap(vc.Elem(), &r.Form) + StructMap(vc.Elem(), &r) //call the controller init function init := vc.MethodByName("Init") From f20ad0916f3a72e77de076accbc7b4b407468e64 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 4 Jun 2013 19:45:48 +0800 Subject: [PATCH 4/4] bug fix --- router.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router.go b/router.go index fe5373e1..2ef445b4 100644 --- a/router.go +++ b/router.go @@ -431,7 +431,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) //Invoke the request handler vc := reflect.New(runrouter.controllerType) - StructMap(vc.Elem(), &r) + StructMap(vc.Elem(), r) //call the controller init function init := vc.MethodByName("Init")