Merge pull request #59 from lunny/master
Add a basic map for url params to controller properties.
Showing
1 changed file
with
89 additions
and
2 deletions
| ... | @@ -7,9 +7,14 @@ import ( | ... | @@ -7,9 +7,14 @@ import ( |
| 7 | "reflect" | 7 | "reflect" |
| 8 | "regexp" | 8 | "regexp" |
| 9 | "runtime" | 9 | "runtime" |
| 10 | "strconv" | ||
| 10 | "strings" | 11 | "strings" |
| 11 | ) | 12 | ) |
| 12 | 13 | ||
| 14 | var ( | ||
| 15 | sc *Controller = &Controller{} | ||
| 16 | ) | ||
| 17 | |||
| 13 | type controllerInfo struct { | 18 | type controllerInfo struct { |
| 14 | pattern string | 19 | pattern string |
| 15 | regex *regexp.Regexp | 20 | regex *regexp.Regexp |
| ... | @@ -44,7 +49,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface) { | ... | @@ -44,7 +49,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface) { |
| 44 | if strings.HasPrefix(part, ":") { | 49 | if strings.HasPrefix(part, ":") { |
| 45 | expr := "(.+)" | 50 | expr := "(.+)" |
| 46 | //a user may choose to override the defult expression | 51 | //a user may choose to override the defult expression |
| 47 | // similar to expressjs: ‘/user/:id([0-9]+)’ | 52 | // similar to expressjs: ‘/user/:id([0-9]+)’ |
| 48 | if index := strings.Index(part, "("); index != -1 { | 53 | if index := strings.Index(part, "("); index != -1 { |
| 49 | expr = part[index:] | 54 | expr = part[index:] |
| 50 | part = part[:index] | 55 | part = part[:index] |
| ... | @@ -118,7 +123,7 @@ func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) { | ... | @@ -118,7 +123,7 @@ func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) { |
| 118 | if strings.HasPrefix(part, ":") { | 123 | if strings.HasPrefix(part, ":") { |
| 119 | expr := "([^/]+)" | 124 | expr := "([^/]+)" |
| 120 | //a user may choose to override the defult expression | 125 | //a user may choose to override the defult expression |
| 121 | // similar to expressjs: ‘/user/:id([0-9]+)’ | 126 | // similar to expressjs: ‘/user/:id([0-9]+)’ |
| 122 | if index := strings.Index(part, "("); index != -1 { | 127 | if index := strings.Index(part, "("); index != -1 { |
| 123 | expr = part[index:] | 128 | expr = part[index:] |
| 124 | part = part[:index] | 129 | part = part[:index] |
| ... | @@ -183,6 +188,85 @@ func (p *ControllerRegistor) FilterPrefixPath(path string, filter http.HandlerFu | ... | @@ -183,6 +188,85 @@ func (p *ControllerRegistor) FilterPrefixPath(path string, filter http.HandlerFu |
| 183 | }) | 188 | }) |
| 184 | } | 189 | } |
| 185 | 190 | ||
| 191 | func StructMap(vc reflect.Value, r *http.Request) error { | ||
| 192 | for k, t := range r.Form { | ||
| 193 | v := t[0] | ||
| 194 | names := strings.Split(k, ".") | ||
| 195 | var value reflect.Value = vc | ||
| 196 | for i, name := range names { | ||
| 197 | name = strings.Title(name) | ||
| 198 | if i == 0 { | ||
| 199 | if reflect.ValueOf(sc).Elem().FieldByName(name).IsValid() { | ||
| 200 | Trace("Controller's property should not be changed by mapper.") | ||
| 201 | break | ||
| 202 | } | ||
| 203 | } | ||
| 204 | if value.Kind() != reflect.Struct { | ||
| 205 | Trace(fmt.Sprintf("arg error, value kind is %v", value.Kind())) | ||
| 206 | break | ||
| 207 | } | ||
| 208 | |||
| 209 | if i != len(names)-1 { | ||
| 210 | value = value.FieldByName(name) | ||
| 211 | if !value.IsValid() { | ||
| 212 | Trace(fmt.Sprintf("(%v value is not valid %v)", name, value)) | ||
| 213 | break | ||
| 214 | } | ||
| 215 | } else { | ||
| 216 | tv := value.FieldByName(name) | ||
| 217 | if !tv.IsValid() { | ||
| 218 | Trace(fmt.Sprintf("struct %v has no field named %v", value, name)) | ||
| 219 | break | ||
| 220 | } | ||
| 221 | if !tv.CanSet() { | ||
| 222 | Trace("can not set " + k) | ||
| 223 | break | ||
| 224 | } | ||
| 225 | var l interface{} | ||
| 226 | switch k := tv.Kind(); k { | ||
| 227 | case reflect.String: | ||
| 228 | l = v | ||
| 229 | case reflect.Bool: | ||
| 230 | l = (v == "true") | ||
| 231 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: | ||
| 232 | x, err := strconv.Atoi(v) | ||
| 233 | if err != nil { | ||
| 234 | Trace("arg " + v + " as int: " + err.Error()) | ||
| 235 | break | ||
| 236 | } | ||
| 237 | l = x | ||
| 238 | case reflect.Int64: | ||
| 239 | x, err := strconv.ParseInt(v, 10, 64) | ||
| 240 | if err != nil { | ||
| 241 | Trace("arg " + v + " as int: " + err.Error()) | ||
| 242 | break | ||
| 243 | } | ||
| 244 | l = x | ||
| 245 | case reflect.Float32, reflect.Float64: | ||
| 246 | x, err := strconv.ParseFloat(v, 64) | ||
| 247 | if err != nil { | ||
| 248 | Trace("arg " + v + " as float64: " + err.Error()) | ||
| 249 | break | ||
| 250 | } | ||
| 251 | l = x | ||
| 252 | case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
| 253 | x, err := strconv.ParseUint(v, 10, 64) | ||
| 254 | if err != nil { | ||
| 255 | Trace("arg " + v + " as int: " + err.Error()) | ||
| 256 | break | ||
| 257 | } | ||
| 258 | l = x | ||
| 259 | case reflect.Struct: | ||
| 260 | Trace("can not set an struct") | ||
| 261 | } | ||
| 262 | |||
| 263 | tv.Set(reflect.ValueOf(l)) | ||
| 264 | } | ||
| 265 | } | ||
| 266 | } | ||
| 267 | return nil | ||
| 268 | } | ||
| 269 | |||
| 186 | // AutoRoute | 270 | // AutoRoute |
| 187 | func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) { | 271 | func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) { |
| 188 | defer func() { | 272 | defer func() { |
| ... | @@ -347,10 +431,13 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -347,10 +431,13 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 347 | //Invoke the request handler | 431 | //Invoke the request handler |
| 348 | vc := reflect.New(runrouter.controllerType) | 432 | vc := reflect.New(runrouter.controllerType) |
| 349 | 433 | ||
| 434 | StructMap(vc.Elem(), r) | ||
| 435 | |||
| 350 | //call the controller init function | 436 | //call the controller init function |
| 351 | init := vc.MethodByName("Init") | 437 | init := vc.MethodByName("Init") |
| 352 | in := make([]reflect.Value, 2) | 438 | in := make([]reflect.Value, 2) |
| 353 | ct := &Context{ResponseWriter: w, Request: r, Params: params} | 439 | ct := &Context{ResponseWriter: w, Request: r, Params: params} |
| 440 | |||
| 354 | in[0] = reflect.ValueOf(ct) | 441 | in[0] = reflect.ValueOf(ct) |
| 355 | in[1] = reflect.ValueOf(runrouter.controllerType.Name()) | 442 | in[1] = reflect.ValueOf(runrouter.controllerType.Name()) |
| 356 | init.Call(in) | 443 | init.Call(in) | ... | ... |
-
Please register or sign in to post a comment