1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-22 13:20:55 +00:00

add url params -> controller's member feature

This commit is contained in:
Lunny Xiao 2013-05-28 16:43:23 +08:00
parent 2dee30183d
commit 8b7cba037e

View File

@ -1,7 +1,6 @@
package beego package beego
import ( import (
"errors"
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
@ -12,6 +11,10 @@ import (
"strings" "strings"
) )
var (
sc *Controller = &Controller{}
)
type controllerInfo struct { type controllerInfo struct {
pattern string pattern string
regex *regexp.Regexp regex *regexp.Regexp
@ -46,7 +49,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface) {
if strings.HasPrefix(part, ":") { if strings.HasPrefix(part, ":") {
expr := "(.+)" expr := "(.+)"
//a user may choose to override the defult expression //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 { if index := strings.Index(part, "("); index != -1 {
expr = part[index:] expr = part[index:]
part = part[:index] part = part[:index]
@ -120,7 +123,7 @@ func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) {
if strings.HasPrefix(part, ":") { if strings.HasPrefix(part, ":") {
expr := "([^/]+)" expr := "([^/]+)"
//a user may choose to override the defult expression //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 { if index := strings.Index(part, "("); index != -1 {
expr = part[index:] expr = part[index:]
part = 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 { func StructMap(vc reflect.Value, params *url.Values) error {
for k, v := range *params {
for k, t := range *params {
v := t[0]
names := strings.Split(k, ".") names := strings.Split(k, ".")
var value reflect.Value = vc var value reflect.Value = vc
for i, name := range names { for i, name := range names {
if i != len(names)-1 { name = strings.Title(name)
if value.Kind() != reflect.Struct { if i == 0 {
return errors.New("arg error") 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() { if !value.IsValid() {
return errors.New("arg error") Trace(fmt.Sprintf("(%v value is not valid %v)", name, value))
break
} }
} else { } else {
tv := value.FieldByName(name) tv := value.FieldByName(name)
fmt.Println(name, tv, tv.Kind())
if !tv.IsValid() { if !tv.IsValid() {
return errors.New("arg error") Trace(fmt.Sprintf("struct %v has no field named %v", value, name))
break
} }
if !tv.CanSet() { if !tv.CanSet() {
return errors.New("can not set " + name) Trace("can not set " + k)
break
} }
var l interface{} var l interface{}
switch k := tv.Kind(); k { 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: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
x, err := strconv.Atoi(v) x, err := strconv.Atoi(v)
if err != nil { if err != nil {
return errors.New("arg " + v + " as int: " + err.Error()) Trace("arg " + v + " as int: " + err.Error())
break
} }
l = x l = x
case reflect.Int64: case reflect.Int64:
x, err := strconv.ParseInt(v, 10, 64) x, err := strconv.ParseInt(v, 10, 64)
if err != nil { if err != nil {
return errors.New("arg " + v + " as int: " + err.Error()) Trace("arg " + v + " as int: " + err.Error())
break
} }
l = x l = x
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
x, err := strconv.ParseFloat(v, 64) x, err := strconv.ParseFloat(v, 64)
if err != nil { if err != nil {
return errors.New("arg " + v + " as float64: " + err.Error()) Trace("arg " + v + " as float64: " + err.Error())
break
} }
l = x l = x
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
x, err := strconv.ParseUint(v, 10, 64) x, err := strconv.ParseUint(v, 10, 64)
if err != nil { if err != nil {
return errors.New("arg " + v + " as int: " + err.Error()) Trace("arg " + v + " as int: " + err.Error())
break
} }
l = x l = x
case reflect.Struct: case reflect.Struct:
fmt.Println("can not set an struct") Trace("can not set an struct")
} }
tv.Set(reflect.ValueOf(l)) tv.Set(reflect.ValueOf(l))
@ -412,13 +432,14 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
//Invoke the request handler //Invoke the request handler
vc := reflect.New(runrouter.controllerType) vc := reflect.New(runrouter.controllerType)
r.ParseForm()
StructMap(vc.Elem(), &r.Form)
//call the controller init function //call the controller init function
init := vc.MethodByName("Init") init := vc.MethodByName("Init")
in := make([]reflect.Value, 2) in := make([]reflect.Value, 2)
ct := &Context{ResponseWriter: w, Request: r, Params: params} ct := &Context{ResponseWriter: w, Request: r, Params: params}
structMap(vc.Elem(), &params)
in[0] = reflect.ValueOf(ct) in[0] = reflect.ValueOf(ct)
in[1] = reflect.ValueOf(runrouter.controllerType.Name()) in[1] = reflect.ValueOf(runrouter.controllerType.Name())
init.Call(in) init.Call(in)