73f0f4f3 by astaxie

Merge pull request #59 from lunny/master

Add a basic map for url params to controller properties.
2 parents b2abb4eb f20ad091
Showing 1 changed file with 87 additions and 0 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
...@@ -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)
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!