diff --git a/filter.go b/filter.go index 7dbc7028..cefd74a1 100644 --- a/filter.go +++ b/filter.go @@ -32,13 +32,13 @@ type FilterRouter struct { // ValidRouter checks if the current request is matched by this filter. // If the request is matched, the values of the URL parameters defined // by the filter pattern are also returned. -func (f *FilterRouter) ValidRouter(url string) (bool, map[string]string) { - isok, params := f.tree.Match(url) +func (f *FilterRouter) ValidRouter(url string, ctx *context.Context) bool { + isok := f.tree.Match(url, ctx) if isok == nil { - return false, nil + return false } if isok, ok := isok.(bool); ok { - return isok, params + return isok } - return false, nil + return false } diff --git a/router.go b/router.go index 01dae8aa..effc2b41 100644 --- a/router.go +++ b/router.go @@ -583,13 +583,7 @@ func (p *ControllerRegister) execFilter(context *beecontext.Context, pos int, ur if filterR.returnOnOutput && context.ResponseWriter.Started { return true } - if ok, params := filterR.ValidRouter(urlPath); ok { - for k, v := range params { - if context.Input.Params == nil { - context.Input.Params = make(map[string]string) - } - context.Input.Params[k] = v - } + if ok := filterR.ValidRouter(urlPath, context); ok { filterR.filterFunc(context) } if filterR.returnOnOutput && context.ResponseWriter.Started { @@ -677,19 +671,16 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) httpMethod = "DELETE" } if t, ok := p.routers[httpMethod]; ok { - runObject, p := t.Match(urlPath) + runObject := t.Match(urlPath, context) if r, ok := runObject.(*controllerInfo); ok { routerInfo = r findrouter = true - if splat, ok := p[":splat"]; ok { + if splat, ok := context.Input.Params[":splat"]; ok { splatlist := strings.Split(splat, "/") for k, v := range splatlist { - p[strconv.Itoa(k)] = v + context.Input.Params[strconv.Itoa(k)] = v } } - if p != nil { - context.Input.Params = p - } } } diff --git a/tree.go b/tree.go index bbda2840..e23ce2fc 100644 --- a/tree.go +++ b/tree.go @@ -19,6 +19,7 @@ import ( "regexp" "strings" + "github.com/astaxie/beego/context" "github.com/astaxie/beego/utils" ) @@ -277,64 +278,60 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, } // Match router to runObject & params -func (t *Tree) Match(pattern string) (runObject interface{}, params map[string]string) { +func (t *Tree) Match(pattern string, ctx *context.Context) (runObject interface{}) { if len(pattern) == 0 || pattern[0] != '/' { - return nil, nil + return nil } - return t.match(splitPath(pattern), nil) + return t.match(splitPath(pattern), nil, ctx) } -func (t *Tree) match(segments []string, wildcardValues []string) (runObject interface{}, params map[string]string) { +func (t *Tree) match(segments []string, wildcardValues []string, ctx *context.Context) (runObject interface{}) { // Handle leaf nodes: if len(segments) == 0 { for _, l := range t.leaves { - if ok, pa := l.match(wildcardValues); ok { - return l.runObject, pa + if ok := l.match(wildcardValues, ctx); ok { + return l.runObject } } if t.wildcard != nil { for _, l := range t.wildcard.leaves { - if ok, pa := l.match(wildcardValues); ok { - return l.runObject, pa + if ok := l.match(wildcardValues, ctx); ok { + return l.runObject } } - } - return nil, nil + return nil } seg, segs := segments[0], segments[1:] subTree, ok := t.fixrouters[seg] if ok { - runObject, params = subTree.match(segs, wildcardValues) + runObject = subTree.match(segs, wildcardValues, ctx) } else if len(segs) == 0 { //.json .xml if subindex := strings.LastIndex(seg, "."); subindex != -1 { subTree, ok = t.fixrouters[seg[:subindex]] if ok { - runObject, params = subTree.match(segs, wildcardValues) + runObject = subTree.match(segs, wildcardValues, ctx) if runObject != nil { - if params == nil { - params = make(map[string]string) - } - params[":ext"] = seg[subindex+1:] - return runObject, params + ctx.Input.Params[":ext"] = seg[subindex+1:] + return runObject } } } } if runObject == nil && t.wildcard != nil { - runObject, params = t.wildcard.match(segs, append(wildcardValues, seg)) + runObject = t.wildcard.match(segs, append(wildcardValues, seg), ctx) } if runObject == nil { for _, l := range t.leaves { - if ok, pa := l.match(append(wildcardValues, segments...)); ok { - return l.runObject, pa + if ok := l.match(append(wildcardValues, segments...), ctx); ok { + return l.runObject } } } - return runObject, params + return runObject } type leafInfo struct { @@ -347,47 +344,43 @@ type leafInfo struct { runObject interface{} } -func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string]string) { +func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok bool) { if leaf.regexps == nil { // has error if len(wildcardValues) == 0 && len(leaf.wildcards) > 0 { if utils.InSlice(":", leaf.wildcards) { - params = make(map[string]string) j := 0 for _, v := range leaf.wildcards { if v == ":" { continue } - params[v] = "" + ctx.Input.Params[v] = "" j++ } - return true, params + return true } - return false, nil + return false } else if len(wildcardValues) == 0 { // static path - return true, nil + return true } // match * if len(leaf.wildcards) == 1 && leaf.wildcards[0] == ":splat" { - params = make(map[string]string) - params[":splat"] = path.Join(wildcardValues...) - return true, params + ctx.Input.Params[":splat"] = path.Join(wildcardValues...) + return true } // match *.* if len(leaf.wildcards) == 3 && leaf.wildcards[0] == "." { - params = make(map[string]string) lastone := wildcardValues[len(wildcardValues)-1] strs := strings.SplitN(lastone, ".", 2) if len(strs) == 2 { - params[":ext"] = strs[1] + ctx.Input.Params[":ext"] = strs[1] } else { - params[":ext"] = "" + ctx.Input.Params[":ext"] = "" } - params[":path"] = path.Join(wildcardValues[:len(wildcardValues)-1]...) + "/" + strs[0] - return true, params + ctx.Input.Params[":path"] = path.Join(wildcardValues[:len(wildcardValues)-1]...) + "/" + strs[0] + return true } // match :id - params = make(map[string]string) j := 0 for _, v := range leaf.wildcards { if v == ":" { @@ -397,38 +390,37 @@ func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string lastone := wildcardValues[len(wildcardValues)-1] strs := strings.SplitN(lastone, ".", 2) if len(strs) == 2 { - params[":ext"] = strs[1] + ctx.Input.Params[":ext"] = strs[1] } else { - params[":ext"] = "" + ctx.Input.Params[":ext"] = "" } if len(wildcardValues[j:]) == 1 { - params[":path"] = strs[0] + ctx.Input.Params[":path"] = strs[0] } else { - params[":path"] = path.Join(wildcardValues[j:]...) + "/" + strs[0] + ctx.Input.Params[":path"] = path.Join(wildcardValues[j:]...) + "/" + strs[0] } - return true, params + return true } if len(wildcardValues) <= j { - return false, nil + return false } - params[v] = wildcardValues[j] + ctx.Input.Params[v] = wildcardValues[j] j++ } - if len(params) != len(wildcardValues) { - return false, nil + if len(ctx.Input.Params) != len(wildcardValues) { + return false } - return true, params + return true } if !leaf.regexps.MatchString(path.Join(wildcardValues...)) { - return false, nil + return false } - params = make(map[string]string) matches := leaf.regexps.FindStringSubmatch(path.Join(wildcardValues...)) for i, match := range matches[1:] { - params[leaf.wildcards[i]] = match + ctx.Input.Params[leaf.wildcards[i]] = match } - return true, params + return true } // "/" -> [] diff --git a/tree_test.go b/tree_test.go index 7fe70f51..22a7b6f1 100644 --- a/tree_test.go +++ b/tree_test.go @@ -14,7 +14,11 @@ package beego -import "testing" +import ( + "testing" + + "github.com/astaxie/beego/context" +) type testinfo struct { url string @@ -27,11 +31,11 @@ var routers []testinfo func init() { routers = make([]testinfo, 0) routers = append(routers, testinfo{"/topic/?:auth:int", "/topic", nil}) - routers = append(routers, testinfo{"/topic/?:auth:int", "/topic/123", map[string]string{":auth":"123"}}) + routers = append(routers, testinfo{"/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}}) routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1", map[string]string{":id": "1"}}) - routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1/2", map[string]string{":id": "1",":auth":"2"}}) + routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1/2", map[string]string{":id": "1", ":auth": "2"}}) routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1", map[string]string{":id": "1"}}) - routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1",":auth":"123"}}) + routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1", ":auth": "123"}}) routers = append(routers, testinfo{"/:id", "/123", map[string]string{":id": "123"}}) routers = append(routers, testinfo{"/hello/?:id", "/hello", map[string]string{":id": ""}}) routers = append(routers, testinfo{"/", "/", nil}) @@ -69,13 +73,14 @@ func TestTreeRouters(t *testing.T) { for _, r := range routers { tr := NewTree() tr.AddRouter(r.url, "astaxie") - obj, param := tr.Match(r.requesturl) + ctx := context.NewContext() + obj := tr.Match(r.requesturl, ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal(r.url + " can't get obj ") } if r.params != nil { for k, v := range r.params { - if vv, ok := param[k]; !ok { + if vv, ok := ctx.Input.Params[k]; !ok { t.Fatal(r.url + " " + r.requesturl + " get param empty:" + k) } else if vv != v { t.Fatal(r.url + " " + r.requesturl + " should be:" + v + " get param:" + vv) @@ -91,47 +96,51 @@ func TestAddTree(t *testing.T) { tr.AddRouter("/shop/:sd/ttt_:id(.+)_:page(.+).html", "astaxie") t1 := NewTree() t1.AddTree("/v1/zl", tr) - obj, param := t1.Match("/v1/zl/shop/123/account") + ctx := context.NewContext() + obj := t1.Match("/v1/zl/shop/123/account", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/v1/zl/shop/:id/account can't get obj ") } - if param == nil { + if len(ctx.Input.Params) == 0 { t.Fatal("get param error") } - if param[":id"] != "123" { + if ctx.Input.Params[":id"] != "123" { t.Fatal("get :id param error") } - obj, param = t1.Match("/v1/zl/shop/123/ttt_1_12.html") + ctx.Input.Reset(ctx) + obj = t1.Match("/v1/zl/shop/123/ttt_1_12.html", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/v1/zl//shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ") } - if param == nil { + if len(ctx.Input.Params) == 0 { t.Fatal("get param error") } - if param[":sd"] != "123" || param[":id"] != "1" || param[":page"] != "12" { + if ctx.Input.Params[":sd"] != "123" || ctx.Input.Params[":id"] != "1" || ctx.Input.Params[":page"] != "12" { t.Fatal("get :sd :id :page param error") } t2 := NewTree() t2.AddTree("/v1/:shopid", tr) - obj, param = t2.Match("/v1/zl/shop/123/account") + ctx.Input.Reset(ctx) + obj = t2.Match("/v1/zl/shop/123/account", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/v1/:shopid/shop/:id/account can't get obj ") } - if param == nil { + if len(ctx.Input.Params) == 0 { t.Fatal("get param error") } - if param[":id"] != "123" || param[":shopid"] != "zl" { + if ctx.Input.Params[":id"] != "123" || ctx.Input.Params[":shopid"] != "zl" { t.Fatal("get :id :shopid param error") } - obj, param = t2.Match("/v1/zl/shop/123/ttt_1_12.html") + ctx.Input.Reset(ctx) + obj = t2.Match("/v1/zl/shop/123/ttt_1_12.html", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/v1/:shopid/shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ") } - if param == nil { + if len(ctx.Input.Params) == 0 { t.Fatal("get :shopid param error") } - if param[":sd"] != "123" || param[":id"] != "1" || param[":page"] != "12" || param[":shopid"] != "zl" { + if ctx.Input.Params[":sd"] != "123" || ctx.Input.Params[":id"] != "1" || ctx.Input.Params[":page"] != "12" || ctx.Input.Params[":shopid"] != "zl" { t.Fatal("get :sd :id :page :shopid param error") } } @@ -142,14 +151,15 @@ func TestAddTree2(t *testing.T) { tr.AddRouter("/shop/:sd/ttt_:id(.+)_:page(.+).html", "astaxie") t3 := NewTree() t3.AddTree("/:version(v1|v2)/:prefix", tr) - obj, param := t3.Match("/v1/zl/shop/123/account") + ctx := context.NewContext() + obj := t3.Match("/v1/zl/shop/123/account", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/:version(v1|v2)/:prefix/shop/:id/account can't get obj ") } - if param == nil { + if len(ctx.Input.Params) == 0 { t.Fatal("get param error") } - if param[":id"] != "123" || param[":prefix"] != "zl" || param[":version"] != "v1" { + if ctx.Input.Params[":id"] != "123" || ctx.Input.Params[":prefix"] != "zl" || ctx.Input.Params[":version"] != "v1" { t.Fatal("get :id :prefix :version param error") } } @@ -160,17 +170,19 @@ func TestAddTree3(t *testing.T) { tr.AddRouter("/shop/:sd/account", "astaxie") t3 := NewTree() t3.AddTree("/table/:num", tr) - obj, param := t3.Match("/table/123/shop/123/account") + ctx := context.NewContext() + obj := t3.Match("/table/123/shop/123/account", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/table/:num/shop/:sd/account can't get obj ") } - if param == nil { + if len(ctx.Input.Params) == 0 { t.Fatal("get param error") } - if param[":num"] != "123" || param[":sd"] != "123" { + if ctx.Input.Params[":num"] != "123" || ctx.Input.Params[":sd"] != "123" { t.Fatal("get :num :sd param error") } - obj, param = t3.Match("/table/123/create") + ctx.Input.Reset(ctx) + obj = t3.Match("/table/123/create", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/table/:num/create can't get obj ") } @@ -182,17 +194,19 @@ func TestAddTree4(t *testing.T) { tr.AddRouter("/shop/:sd/:account", "astaxie") t4 := NewTree() t4.AddTree("/:info:int/:num/:id", tr) - obj, param := t4.Match("/12/123/456/shop/123/account") + ctx := context.NewContext() + obj := t4.Match("/12/123/456/shop/123/account", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/:info:int/:num/:id/shop/:sd/:account can't get obj ") } - if param == nil { + if len(ctx.Input.Params) == 0 { t.Fatal("get param error") } - if param[":info"] != "12" || param[":num"] != "123" || param[":id"] != "456" || param[":sd"] != "123" || param[":account"] != "account" { + if ctx.Input.Params[":info"] != "12" || ctx.Input.Params[":num"] != "123" || ctx.Input.Params[":id"] != "456" || ctx.Input.Params[":sd"] != "123" || ctx.Input.Params[":account"] != "account" { t.Fatal("get :info :num :id :sd :account param error") } - obj, param = t4.Match("/12/123/456/create") + ctx.Input.Reset(ctx) + obj = t4.Match("/12/123/456/create", ctx) if obj == nil || obj.(string) != "astaxie" { t.Fatal("/:info:int/:num/:id/create can't get obj ") }