fix #315
Showing
4 changed files
with
159 additions
and
63 deletions
| ... | @@ -139,6 +139,7 @@ func (input *BeegoInput) Param(key string) string { | ... | @@ -139,6 +139,7 @@ func (input *BeegoInput) Param(key string) string { |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | func (input *BeegoInput) Query(key string) string { | 141 | func (input *BeegoInput) Query(key string) string { |
| 142 | input.req.ParseForm() | ||
| 142 | return input.req.Form.Get(key) | 143 | return input.req.Form.Get(key) |
| 143 | } | 144 | } |
| 144 | 145 | ... | ... |
| ... | @@ -2,36 +2,143 @@ package beego | ... | @@ -2,36 +2,143 @@ package beego |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "regexp" | 4 | "regexp" |
| 5 | "strings" | ||
| 5 | ) | 6 | ) |
| 6 | 7 | ||
| 7 | type FilterRouter struct { | 8 | type FilterRouter struct { |
| 8 | pattern string | 9 | pattern string |
| 9 | regex *regexp.Regexp | 10 | regex *regexp.Regexp |
| 10 | filterFunc FilterFunc | 11 | filterFunc FilterFunc |
| 11 | hasregex bool | 12 | hasregex bool |
| 12 | params map[int]string | 13 | params map[int]string |
| 14 | parseParams map[string]string | ||
| 13 | } | 15 | } |
| 14 | 16 | ||
| 15 | func (mr *FilterRouter) ValidRouter(router string) bool { | 17 | func (mr *FilterRouter) ValidRouter(router string) (bool, map[string]string) { |
| 16 | if mr.pattern == "" { | 18 | if mr.pattern == "" { |
| 17 | return true | 19 | return true, nil |
| 18 | } | 20 | } |
| 19 | if mr.pattern == "*" { | 21 | if mr.pattern == "*" { |
| 20 | return true | 22 | return true, nil |
| 21 | } | 23 | } |
| 22 | if router == mr.pattern { | 24 | if router == mr.pattern { |
| 23 | return true | 25 | return true, nil |
| 24 | } | 26 | } |
| 25 | if mr.hasregex { | 27 | if mr.hasregex { |
| 26 | if mr.regex.MatchString(router) { | 28 | if !mr.regex.MatchString(router) { |
| 27 | return true | 29 | return false, nil |
| 28 | } | 30 | } |
| 29 | matches := mr.regex.FindStringSubmatch(router) | 31 | matches := mr.regex.FindStringSubmatch(router) |
| 30 | if len(matches) > 0 { | 32 | if len(matches) > 0 { |
| 31 | if len(matches[0]) == len(router) { | 33 | if len(matches[0]) == len(router) { |
| 32 | return true | 34 | params := make(map[string]string) |
| 35 | for i, match := range matches[1:] { | ||
| 36 | params[mr.params[i]] = match | ||
| 37 | } | ||
| 38 | return true, params | ||
| 33 | } | 39 | } |
| 34 | } | 40 | } |
| 35 | } | 41 | } |
| 36 | return false | 42 | return false, nil |
| 43 | } | ||
| 44 | |||
| 45 | func buildFilter(pattern string, filter FilterFunc) *FilterRouter { | ||
| 46 | mr := new(FilterRouter) | ||
| 47 | mr.params = make(map[int]string) | ||
| 48 | mr.filterFunc = filter | ||
| 49 | parts := strings.Split(pattern, "/") | ||
| 50 | j := 0 | ||
| 51 | for i, part := range parts { | ||
| 52 | if strings.HasPrefix(part, ":") { | ||
| 53 | expr := "(.+)" | ||
| 54 | //a user may choose to override the default expression | ||
| 55 | // similar to expressjs: ‘/user/:id([0-9]+)’ | ||
| 56 | if index := strings.Index(part, "("); index != -1 { | ||
| 57 | expr = part[index:] | ||
| 58 | part = part[:index] | ||
| 59 | //match /user/:id:int ([0-9]+) | ||
| 60 | //match /post/:username:string ([\w]+) | ||
| 61 | } else if lindex := strings.LastIndex(part, ":"); lindex != 0 { | ||
| 62 | switch part[lindex:] { | ||
| 63 | case ":int": | ||
| 64 | expr = "([0-9]+)" | ||
| 65 | part = part[:lindex] | ||
| 66 | case ":string": | ||
| 67 | expr = `([\w]+)` | ||
| 68 | part = part[:lindex] | ||
| 69 | } | ||
| 70 | } | ||
| 71 | mr.params[j] = part | ||
| 72 | parts[i] = expr | ||
| 73 | j++ | ||
| 74 | } | ||
| 75 | if strings.HasPrefix(part, "*") { | ||
| 76 | expr := "(.+)" | ||
| 77 | if part == "*.*" { | ||
| 78 | mr.params[j] = ":path" | ||
| 79 | parts[i] = "([^.]+).([^.]+)" | ||
| 80 | j++ | ||
| 81 | mr.params[j] = ":ext" | ||
| 82 | j++ | ||
| 83 | } else { | ||
| 84 | mr.params[j] = ":splat" | ||
| 85 | parts[i] = expr | ||
| 86 | j++ | ||
| 87 | } | ||
| 88 | } | ||
| 89 | //url like someprefix:id(xxx).html | ||
| 90 | if strings.Contains(part, ":") && strings.Contains(part, "(") && strings.Contains(part, ")") { | ||
| 91 | var out []rune | ||
| 92 | var start bool | ||
| 93 | var startexp bool | ||
| 94 | var param []rune | ||
| 95 | var expt []rune | ||
| 96 | for _, v := range part { | ||
| 97 | if start { | ||
| 98 | if v != '(' { | ||
| 99 | param = append(param, v) | ||
| 100 | continue | ||
| 101 | } | ||
| 102 | } | ||
| 103 | if startexp { | ||
| 104 | if v != ')' { | ||
| 105 | expt = append(expt, v) | ||
| 106 | continue | ||
| 107 | } | ||
| 108 | } | ||
| 109 | if v == ':' { | ||
| 110 | param = make([]rune, 0) | ||
| 111 | param = append(param, ':') | ||
| 112 | start = true | ||
| 113 | } else if v == '(' { | ||
| 114 | startexp = true | ||
| 115 | start = false | ||
| 116 | mr.params[j] = string(param) | ||
| 117 | j++ | ||
| 118 | expt = make([]rune, 0) | ||
| 119 | expt = append(expt, '(') | ||
| 120 | } else if v == ')' { | ||
| 121 | startexp = false | ||
| 122 | expt = append(expt, ')') | ||
| 123 | out = append(out, expt...) | ||
| 124 | } else { | ||
| 125 | out = append(out, v) | ||
| 126 | } | ||
| 127 | } | ||
| 128 | parts[i] = string(out) | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | if j != 0 { | ||
| 133 | pattern = strings.Join(parts, "/") | ||
| 134 | regex, regexErr := regexp.Compile(pattern) | ||
| 135 | if regexErr != nil { | ||
| 136 | //TODO add error handling here to avoid panic | ||
| 137 | panic(regexErr) | ||
| 138 | } | ||
| 139 | mr.regex = regex | ||
| 140 | mr.hasregex = true | ||
| 141 | } | ||
| 142 | mr.pattern = pattern | ||
| 143 | return mr | ||
| 37 | } | 144 | } | ... | ... |
fiter_test.go
0 → 100644
| 1 | package beego | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "github.com/astaxie/beego/context" | ||
| 5 | "net/http" | ||
| 6 | "net/http/httptest" | ||
| 7 | "testing" | ||
| 8 | ) | ||
| 9 | |||
| 10 | var FilterUser = func(ctx *context.Context) { | ||
| 11 | ctx.Output.Body([]byte("i am " + ctx.Input.Params[":last"] + ctx.Input.Params[":first"])) | ||
| 12 | } | ||
| 13 | |||
| 14 | func TestFilter(t *testing.T) { | ||
| 15 | r, _ := http.NewRequest("GET", "/person/asta/Xie", nil) | ||
| 16 | w := httptest.NewRecorder() | ||
| 17 | handler := NewControllerRegistor() | ||
| 18 | handler.AddFilter("/person/:last/:first", "AfterStatic", FilterUser) | ||
| 19 | handler.Add("/person/:last/:first", &TestController{}) | ||
| 20 | handler.ServeHTTP(w, r) | ||
| 21 | if w.Body.String() != "i am astaXie" { | ||
| 22 | t.Errorf("user define func can't run") | ||
| 23 | } | ||
| 24 | } |
| ... | @@ -222,49 +222,6 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) { | ... | @@ -222,49 +222,6 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) { |
| 222 | } | 222 | } |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | func buildFilter(pattern string, filter FilterFunc) *FilterRouter { | ||
| 226 | mr := new(FilterRouter) | ||
| 227 | mr.filterFunc = filter | ||
| 228 | parts := strings.Split(pattern, "/") | ||
| 229 | j := 0 | ||
| 230 | for i, part := range parts { | ||
| 231 | if strings.HasPrefix(part, ":") { | ||
| 232 | expr := "(.+)" | ||
| 233 | //a user may choose to override the default expression | ||
| 234 | // similar to expressjs: ‘/user/:id([0-9]+)’ | ||
| 235 | if index := strings.Index(part, "("); index != -1 { | ||
| 236 | expr = part[index:] | ||
| 237 | part = part[:index] | ||
| 238 | //match /user/:id:int ([0-9]+) | ||
| 239 | //match /post/:username:string ([\w]+) | ||
| 240 | } else if lindex := strings.LastIndex(part, ":"); lindex != 0 { | ||
| 241 | switch part[lindex:] { | ||
| 242 | case ":int": | ||
| 243 | expr = "([0-9]+)" | ||
| 244 | part = part[:lindex] | ||
| 245 | case ":string": | ||
| 246 | expr = `([\w]+)` | ||
| 247 | part = part[:lindex] | ||
| 248 | } | ||
| 249 | } | ||
| 250 | parts[i] = expr | ||
| 251 | j++ | ||
| 252 | } | ||
| 253 | } | ||
| 254 | if j != 0 { | ||
| 255 | pattern = strings.Join(parts, "/") | ||
| 256 | regex, regexErr := regexp.Compile(pattern) | ||
| 257 | if regexErr != nil { | ||
| 258 | //TODO add error handling here to avoid panic | ||
| 259 | panic(regexErr) | ||
| 260 | } | ||
| 261 | mr.regex = regex | ||
| 262 | mr.hasregex = true | ||
| 263 | } | ||
| 264 | mr.pattern = pattern | ||
| 265 | return mr | ||
| 266 | } | ||
| 267 | |||
| 268 | func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) { | 225 | func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) { |
| 269 | mr := buildFilter(pattern, filter) | 226 | mr := buildFilter(pattern, filter) |
| 270 | switch action { | 227 | switch action { |
| ... | @@ -469,7 +426,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -469,7 +426,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 469 | if p.enableFilter { | 426 | if p.enableFilter { |
| 470 | if l, ok := p.filters[BeforeRouter]; ok { | 427 | if l, ok := p.filters[BeforeRouter]; ok { |
| 471 | for _, filterR := range l { | 428 | for _, filterR := range l { |
| 472 | if filterR.ValidRouter(r.URL.Path) { | 429 | if ok, p := filterR.ValidRouter(r.URL.Path); ok { |
| 430 | context.Input.Params = p | ||
| 473 | filterR.filterFunc(context) | 431 | filterR.filterFunc(context) |
| 474 | if w.started { | 432 | if w.started { |
| 475 | goto Admin | 433 | goto Admin |
| ... | @@ -516,7 +474,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -516,7 +474,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 516 | if p.enableFilter { | 474 | if p.enableFilter { |
| 517 | if l, ok := p.filters[AfterStatic]; ok { | 475 | if l, ok := p.filters[AfterStatic]; ok { |
| 518 | for _, filterR := range l { | 476 | for _, filterR := range l { |
| 519 | if filterR.ValidRouter(r.URL.Path) { | 477 | if ok, p := filterR.ValidRouter(r.URL.Path); ok { |
| 478 | context.Input.Params = p | ||
| 520 | filterR.filterFunc(context) | 479 | filterR.filterFunc(context) |
| 521 | if w.started { | 480 | if w.started { |
| 522 | goto Admin | 481 | goto Admin |
| ... | @@ -591,7 +550,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -591,7 +550,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 591 | if p.enableFilter { | 550 | if p.enableFilter { |
| 592 | if l, ok := p.filters[BeforeExec]; ok { | 551 | if l, ok := p.filters[BeforeExec]; ok { |
| 593 | for _, filterR := range l { | 552 | for _, filterR := range l { |
| 594 | if filterR.ValidRouter(r.URL.Path) { | 553 | if ok, p := filterR.ValidRouter(r.URL.Path); ok { |
| 554 | context.Input.Params = p | ||
| 595 | filterR.filterFunc(context) | 555 | filterR.filterFunc(context) |
| 596 | if w.started { | 556 | if w.started { |
| 597 | goto Admin | 557 | goto Admin |
| ... | @@ -746,7 +706,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -746,7 +706,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 746 | if p.enableFilter { | 706 | if p.enableFilter { |
| 747 | if l, ok := p.filters[AfterExec]; ok { | 707 | if l, ok := p.filters[AfterExec]; ok { |
| 748 | for _, filterR := range l { | 708 | for _, filterR := range l { |
| 749 | if filterR.ValidRouter(r.URL.Path) { | 709 | if ok, p := filterR.ValidRouter(r.URL.Path); ok { |
| 710 | context.Input.Params = p | ||
| 750 | filterR.filterFunc(context) | 711 | filterR.filterFunc(context) |
| 751 | if w.started { | 712 | if w.started { |
| 752 | goto Admin | 713 | goto Admin |
| ... | @@ -795,7 +756,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -795,7 +756,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 795 | if p.enableFilter { | 756 | if p.enableFilter { |
| 796 | if l, ok := p.filters[BeforeExec]; ok { | 757 | if l, ok := p.filters[BeforeExec]; ok { |
| 797 | for _, filterR := range l { | 758 | for _, filterR := range l { |
| 798 | if filterR.ValidRouter(r.URL.Path) { | 759 | if ok, p := filterR.ValidRouter(r.URL.Path); ok { |
| 760 | context.Input.Params = p | ||
| 799 | filterR.filterFunc(context) | 761 | filterR.filterFunc(context) |
| 800 | if w.started { | 762 | if w.started { |
| 801 | goto Admin | 763 | goto Admin |
| ... | @@ -850,7 +812,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -850,7 +812,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 850 | if p.enableFilter { | 812 | if p.enableFilter { |
| 851 | if l, ok := p.filters[AfterExec]; ok { | 813 | if l, ok := p.filters[AfterExec]; ok { |
| 852 | for _, filterR := range l { | 814 | for _, filterR := range l { |
| 853 | if filterR.ValidRouter(r.URL.Path) { | 815 | if ok, p := filterR.ValidRouter(r.URL.Path); ok { |
| 816 | context.Input.Params = p | ||
| 854 | filterR.filterFunc(context) | 817 | filterR.filterFunc(context) |
| 855 | if w.started { | 818 | if w.started { |
| 856 | goto Admin | 819 | goto Admin |
| ... | @@ -878,7 +841,8 @@ Admin: | ... | @@ -878,7 +841,8 @@ Admin: |
| 878 | if p.enableFilter { | 841 | if p.enableFilter { |
| 879 | if l, ok := p.filters[FinishRouter]; ok { | 842 | if l, ok := p.filters[FinishRouter]; ok { |
| 880 | for _, filterR := range l { | 843 | for _, filterR := range l { |
| 881 | if filterR.ValidRouter(r.URL.Path) { | 844 | if ok, p := filterR.ValidRouter(r.URL.Path); ok { |
| 845 | context.Input.Params = p | ||
| 882 | filterR.filterFunc(context) | 846 | filterR.filterFunc(context) |
| 883 | if w.started { | 847 | if w.started { |
| 884 | break | 848 | break | ... | ... |
-
Please register or sign in to post a comment