From 29752e25758f8cf3841c1e9631f4f3b155aabf1d Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 16 Dec 2015 23:11:03 +0800 Subject: [PATCH] refactor router --- context/input.go | 46 ++++++-- controller.go | 2 +- controller_test.go | 15 ++- filter_test.go | 2 +- router.go | 8 +- router_test.go | 2 +- tree.go | 257 +++++++++++++++++++++++---------------------- tree_test.go | 39 +++---- 8 files changed, 206 insertions(+), 165 deletions(-) diff --git a/context/input.go b/context/input.go index 9649e14f..3f73787d 100644 --- a/context/input.go +++ b/context/input.go @@ -33,6 +33,7 @@ var ( acceptsHTMLRegex = regexp.MustCompile(`(text/html|application/xhtml\+xml)(?:,|$)`) acceptsXMLRegex = regexp.MustCompile(`(application/xml|text/xml)(?:,|$)`) acceptsJSONRegex = regexp.MustCompile(`(application/json)(?:,|$)`) + maxParam = 50 ) // BeegoInput operates the http request header, data, cookie and body. @@ -40,16 +41,17 @@ var ( type BeegoInput struct { Context *Context CruSession session.Store - Params map[string]string - Data map[interface{}]interface{} // store some values in this context when calling context in filter or controller. + pnames []string + pvalues []string + data map[interface{}]interface{} // store some values in this context when calling context in filter or controller. RequestBody []byte } // NewInput return BeegoInput generated by Context. func NewInput() *BeegoInput { return &BeegoInput{ - Params: make(map[string]string), - Data: make(map[interface{}]interface{}), + pvalues: make([]string, maxParam), + data: make(map[interface{}]interface{}), } } @@ -57,8 +59,8 @@ func NewInput() *BeegoInput { func (input *BeegoInput) Reset(ctx *Context) { input.Context = ctx input.CruSession = nil - input.Params = make(map[string]string) - input.Data = make(map[interface{}]interface{}) + input.pnames = input.pnames[:0] + input.data = nil input.RequestBody = []byte{} } @@ -254,14 +256,27 @@ func (input *BeegoInput) UserAgent() string { return input.Header("User-Agent") } +// ParamsLen return the length of the params +func (input *BeegoInput) ParamsLen() int { + return len(input.pnames) +} + // Param returns router param by a given key. func (input *BeegoInput) Param(key string) string { - if v, ok := input.Params[key]; ok { - return v + for i, v := range input.pnames { + if v == key { + return input.pvalues[i] + } } return "" } +// SetParam will set the param with key and value +func (input *BeegoInput) SetParam(key, val string) { + input.pvalues[len(input.pnames)] = val + input.pnames = append(input.pnames, key) +} + // Query returns input data item string by a given string. func (input *BeegoInput) Query(key string) string { if val := input.Param(key); val != "" { @@ -305,9 +320,17 @@ func (input *BeegoInput) CopyBody() []byte { return requestbody } +// Data return the implicit data in the input +func (input *BeegoInput) Data() map[interface{}]interface{} { + if input.data == nil { + input.data = make(map[interface{}]interface{}) + } + return input.data +} + // GetData returns the stored data in this context. func (input *BeegoInput) GetData(key interface{}) interface{} { - if v, ok := input.Data[key]; ok { + if v, ok := input.data[key]; ok { return v } return nil @@ -316,7 +339,10 @@ func (input *BeegoInput) GetData(key interface{}) interface{} { // SetData stores data with given key in this context. // This data are only available in this context. func (input *BeegoInput) SetData(key, val interface{}) { - input.Data[key] = val + if input.data == nil { + input.data = make(map[interface{}]interface{}) + } + input.data[key] = val } // ParseFormOrMulitForm parseForm or parseMultiForm based on Content-type diff --git a/controller.go b/controller.go index 826ad54d..ebe99c5c 100644 --- a/controller.go +++ b/controller.go @@ -105,7 +105,7 @@ func (c *Controller) Init(ctx *context.Context, controllerName, actionName strin c.AppController = app c.EnableRender = true c.EnableXSRF = true - c.Data = ctx.Input.Data + c.Data = ctx.Input.Data() c.methodMapping = make(map[string]func()) } diff --git a/controller_test.go b/controller_test.go index ebf38b2c..51d3a5b7 100644 --- a/controller_test.go +++ b/controller_test.go @@ -21,7 +21,8 @@ import ( ) func TestGetInt(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} + i := context.NewInput() + i.SetParam("age", "40") ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} val, _ := ctrlr.GetInt("age") @@ -31,7 +32,8 @@ func TestGetInt(t *testing.T) { } func TestGetInt8(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} + i := context.NewInput() + i.SetParam("age", "40") ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} val, _ := ctrlr.GetInt8("age") @@ -42,7 +44,8 @@ func TestGetInt8(t *testing.T) { } func TestGetInt16(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} + i := context.NewInput() + i.SetParam("age", "40") ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} val, _ := ctrlr.GetInt16("age") @@ -52,7 +55,8 @@ func TestGetInt16(t *testing.T) { } func TestGetInt32(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} + i := context.NewInput() + i.SetParam("age", "40") ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} val, _ := ctrlr.GetInt32("age") @@ -62,7 +66,8 @@ func TestGetInt32(t *testing.T) { } func TestGetInt64(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} + i := context.NewInput() + i.SetParam("age", "40") ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} val, _ := ctrlr.GetInt64("age") diff --git a/filter_test.go b/filter_test.go index b1cd9c94..d9928d8d 100644 --- a/filter_test.go +++ b/filter_test.go @@ -29,7 +29,7 @@ func init() { } var FilterUser = func(ctx *context.Context) { - ctx.Output.Body([]byte("i am " + ctx.Input.Params[":last"] + ctx.Input.Params[":first"])) + ctx.Output.Body([]byte("i am " + ctx.Input.Param(":last") + ctx.Input.Param(":first"))) } func TestFilter(t *testing.T) { diff --git a/router.go b/router.go index effc2b41..53469b21 100644 --- a/router.go +++ b/router.go @@ -466,8 +466,8 @@ func (p *ControllerRegister) URLFor(endpoint string, values ...interface{}) stri } func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName string, params map[string]string, httpMethod string) (bool, string) { - for k, subtree := range t.fixrouters { - u := path.Join(url, k) + for _, subtree := range t.fixrouters { + u := path.Join(url, subtree.prefix) ok, u := p.geturl(subtree, u, controllName, methodName, params, httpMethod) if ok { return ok, u @@ -675,10 +675,10 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) if r, ok := runObject.(*controllerInfo); ok { routerInfo = r findrouter = true - if splat, ok := context.Input.Params[":splat"]; ok { + if splat := context.Input.Param(":splat"); splat != "" { splatlist := strings.Split(splat, "/") for k, v := range splatlist { - context.Input.Params[strconv.Itoa(k)] = v + context.Input.SetParam(strconv.Itoa(k), v) } } } diff --git a/router_test.go b/router_test.go index 9598f99c..b0ae7a18 100644 --- a/router_test.go +++ b/router_test.go @@ -45,7 +45,7 @@ func (tc *TestController) List() { } func (tc *TestController) Params() { - tc.Ctx.Output.Body([]byte(tc.Ctx.Input.Params["0"] + tc.Ctx.Input.Params["1"] + tc.Ctx.Input.Params["2"])) + tc.Ctx.Output.Body([]byte(tc.Ctx.Input.Param("0") + tc.Ctx.Input.Param("1") + tc.Ctx.Input.Param("2"))) } func (tc *TestController) Myext() { diff --git a/tree.go b/tree.go index e23ce2fc..dbcc63c9 100644 --- a/tree.go +++ b/tree.go @@ -23,26 +23,28 @@ import ( "github.com/astaxie/beego/utils" ) +var ( + allowSuffixExt = []string{".json", ".xml", ".html"} +) + // Tree has three elements: FixRouter/wildcard/leaves // fixRouter sotres Fixed Router // wildcard stores params // leaves store the endpoint information type Tree struct { + //prefix set for static router + prefix string //search fix route first - fixrouters map[string]*Tree - + fixrouters []*Tree //if set, failure to match fixrouters search then search wildcard wildcard *Tree - //if set, failure to match wildcard search leaves []*leafInfo } // NewTree return a new Tree func NewTree() *Tree { - return &Tree{ - fixrouters: make(map[string]*Tree), - } + return &Tree{} } // AddTree will add tree to the exist Tree @@ -57,15 +59,31 @@ func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg st } seg := segments[0] iswild, params, regexpStr := splitSegment(seg) + // if it's ? meaning can igone this, so add one more rule for it + if len(params) > 0 && params[0] == ":" { + params = params[1:] + if len(segments[1:]) > 0 { + t.addtree(segments[1:], tree, append(wildcards, params...), reg) + } else { + filterTreeWithPrefix(tree, wildcards, reg) + } + } + //Rule: /login/*/access match /login/2009/11/access + //if already has *, and when loop the access, should as a regexpStr + if !iswild && utils.InSlice(":splat", wildcards) { + iswild = true + regexpStr = seg + } + //Rule: /user/:id/* + if seg == "*" && len(wildcards) > 0 && reg == "" { + regexpStr = "(.+)" + } if len(segments) == 1 { if iswild { if regexpStr != "" { if reg == "" { rr := "" for _, w := range wildcards { - if w == "." || w == ":" { - continue - } if w == ":splat" { rr = rr + "(.+)/" } else { @@ -94,10 +112,12 @@ func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg st } else { reg = strings.Trim(reg+"/"+regexpStr, "/") filterTreeWithPrefix(tree, append(wildcards, params...), reg) - t.fixrouters[seg] = tree + tree.prefix = seg + t.fixrouters = append(t.fixrouters, tree) } return } + if iswild { if t.wildcard == nil { t.wildcard = NewTree() @@ -106,9 +126,6 @@ func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg st if reg == "" { rr := "" for _, w := range wildcards { - if w == "." || w == ":" { - continue - } if w == ":splat" { rr = rr + "(.+)/" } else { @@ -122,20 +139,23 @@ func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg st } else if reg != "" { if seg == "*.*" { regexpStr = "([^.]+).(.+)" + params = params[1:] } else { - for _, w := range params { - if w == "." || w == ":" { - continue - } + for _ = range params { regexpStr = "([^/]+)/" + regexpStr } } + } else { + if seg == "*.*" { + params = params[1:] + } } reg = strings.TrimRight(strings.TrimRight(reg, "/")+"/"+regexpStr, "/") t.wildcard.addtree(segments[1:], tree, append(wildcards, params...), reg) } else { subTree := NewTree() - t.fixrouters[seg] = subTree + subTree.prefix = seg + t.fixrouters = append(t.fixrouters, subTree) subTree.addtree(segments[1:], tree, append(wildcards, params...), reg) } } @@ -154,9 +174,6 @@ func filterTreeWithPrefix(t *Tree, wildcards []string, reg string) { l.regexps = regexp.MustCompile("^" + reg + "/" + strings.Trim(l.regexps.String(), "^$") + "$") } else { for _, v := range l.wildcards { - if v == ":" || v == "." { - continue - } if v == ":splat" { reg = reg + "/(.+)" } else { @@ -166,21 +183,10 @@ func filterTreeWithPrefix(t *Tree, wildcards []string, reg string) { l.regexps = regexp.MustCompile("^" + reg + "$") l.wildcards = append(wildcards, l.wildcards...) } - filterCards := []string{} - for _, v := range l.wildcards { - if v == ":" || v == "." { - continue - } - filterCards = append(filterCards, v) - } - l.wildcards = filterCards } else { l.wildcards = append(wildcards, l.wildcards...) if l.regexps != nil { for _, w := range wildcards { - if w == "." || w == ":" { - continue - } if w == ":splat" { reg = "(.+)/" + reg } else { @@ -203,32 +209,26 @@ func (t *Tree) AddRouter(pattern string, runObject interface{}) { func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, reg string) { if len(segments) == 0 { if reg != "" { - filterCards := []string{} - for _, v := range wildcards { - if v == ":" || v == "." { - continue - } - filterCards = append(filterCards, v) - } - t.leaves = append(t.leaves, &leafInfo{runObject: route, wildcards: filterCards, regexps: regexp.MustCompile("^" + reg + "$")}) + t.leaves = append(t.leaves, &leafInfo{runObject: route, wildcards: wildcards, regexps: regexp.MustCompile("^" + reg + "$")}) } else { t.leaves = append(t.leaves, &leafInfo{runObject: route, wildcards: wildcards}) } - for i, v := range wildcards { - if v == ":" { - t.leaves = append(t.leaves, &leafInfo{runObject: route, wildcards: wildcards[:i+1]}) - } - } } else { seg := segments[0] iswild, params, regexpStr := splitSegment(seg) - //for the router /login/*/access match /login/2009/11/access + // if it's ? meaning can igone this, so add one more rule for it + if len(params) > 0 && params[0] == ":" { + t.addseg(segments[1:], route, wildcards, reg) + params = params[1:] + } + //Rule: /login/*/access match /login/2009/11/access + //if already has *, and when loop the access, should as a regexpStr if !iswild && utils.InSlice(":splat", wildcards) { iswild = true regexpStr = seg } + //Rule: /user/:id/* if seg == "*" && len(wildcards) > 0 && reg == "" { - iswild = true regexpStr = "(.+)" } if iswild { @@ -239,9 +239,6 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, if reg == "" { rr := "" for _, w := range wildcards { - if w == "." || w == ":" { - continue - } if w == ":splat" { rr = rr + "(.+)/" } else { @@ -255,22 +252,31 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, } else if reg != "" { if seg == "*.*" { regexpStr = "/([^.]+).(.+)" + params = params[1:] } else { - for _, w := range params { - - if w == "." || w == ":" { - continue - } + for _ = range params { regexpStr = "/([^/]+)" + regexpStr } } + } else { + if seg == "*.*" { + params = params[1:] + } } t.wildcard.addseg(segments[1:], route, append(wildcards, params...), reg+regexpStr) } else { - subTree, ok := t.fixrouters[seg] + var ok bool + var subTree *Tree + for _, subTree = range t.fixrouters { + if t.prefix == seg { + ok = true + break + } + } if !ok { subTree = NewTree() - t.fixrouters[seg] = subTree + subTree.prefix = seg + t.fixrouters = append(t.fixrouters, subTree) } subTree.addseg(segments[1:], route, wildcards, reg) } @@ -282,13 +288,18 @@ func (t *Tree) Match(pattern string, ctx *context.Context) (runObject interface{ if len(pattern) == 0 || pattern[0] != '/' { return nil } - - return t.match(splitPath(pattern), nil, ctx) + return t.match(pattern, nil, ctx) } -func (t *Tree) match(segments []string, wildcardValues []string, ctx *context.Context) (runObject interface{}) { +func (t *Tree) match(pattern string, wildcardValues []string, ctx *context.Context) (runObject interface{}) { + if len(pattern) > 0 { + i := 0 + for ; i < len(pattern) && pattern[i] == '/'; i++ { + } + pattern = pattern[i:] + } // Handle leaf nodes: - if len(segments) == 0 { + if len(pattern) == 0 { for _, l := range t.leaves { if ok := l.match(wildcardValues, ctx); ok { return l.runObject @@ -303,28 +314,47 @@ func (t *Tree) match(segments []string, wildcardValues []string, ctx *context.Co } return nil } - - seg, segs := segments[0], segments[1:] - - subTree, ok := t.fixrouters[seg] - if ok { - 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 = subTree.match(segs, wildcardValues, ctx) - if runObject != nil { - ctx.Input.Params[":ext"] = seg[subindex+1:] - return runObject + var seg string + i, l := 0, len(pattern) + for ; i < l && pattern[i] != '/'; i++ { + } + if i == 0 { + seg = pattern + pattern = "" + } else { + seg = pattern[:i] + pattern = pattern[i:] + } + for _, subTree := range t.fixrouters { + if subTree.prefix == seg { + runObject = subTree.match(pattern, wildcardValues, ctx) + if runObject != nil { + break + } + } + } + if runObject == nil { + // Filter the .json .xml .html extension + for _, str := range allowSuffixExt { + if strings.HasSuffix(seg, str) { + for _, subTree := range t.fixrouters { + if subTree.prefix == seg[:len(seg)-len(str)] { + runObject = subTree.match(pattern, wildcardValues, ctx) + if runObject != nil { + ctx.Input.SetParam(":ext", str[1:]) + } + } } } } } if runObject == nil && t.wildcard != nil { - runObject = t.wildcard.match(segs, append(wildcardValues, seg), ctx) + runObject = t.wildcard.match(pattern, append(wildcardValues, seg), ctx) } + if runObject == nil { + segments := splitPath(pattern) + wildcardValues = append(wildcardValues, seg) for _, l := range t.leaves { if ok := l.match(append(wildcardValues, segments...), ctx); ok { return l.runObject @@ -345,71 +375,48 @@ type leafInfo struct { } func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok bool) { + //fmt.Println("Leaf:", wildcardValues, leaf.wildcards, leaf.regexps) if leaf.regexps == nil { - // has error - if len(wildcardValues) == 0 && len(leaf.wildcards) > 0 { - if utils.InSlice(":", leaf.wildcards) { - j := 0 - for _, v := range leaf.wildcards { - if v == ":" { - continue - } - ctx.Input.Params[v] = "" - j++ - } - return true - } - return false - } else if len(wildcardValues) == 0 { // static path + if len(wildcardValues) == 0 { // static path return true } // match * if len(leaf.wildcards) == 1 && leaf.wildcards[0] == ":splat" { - ctx.Input.Params[":splat"] = path.Join(wildcardValues...) + ctx.Input.SetParam(":splat", path.Join(wildcardValues...)) return true } - // match *.* - if len(leaf.wildcards) == 3 && leaf.wildcards[0] == "." { - lastone := wildcardValues[len(wildcardValues)-1] - strs := strings.SplitN(lastone, ".", 2) - if len(strs) == 2 { - ctx.Input.Params[":ext"] = strs[1] - } else { - ctx.Input.Params[":ext"] = "" - } - ctx.Input.Params[":path"] = path.Join(wildcardValues[:len(wildcardValues)-1]...) + "/" + strs[0] - return true - } - // match :id - j := 0 - for _, v := range leaf.wildcards { - if v == ":" { - continue - } - if v == "." { + // match *.* or :id + if len(leaf.wildcards) >= 2 && leaf.wildcards[len(leaf.wildcards)-2] == ":path" && leaf.wildcards[len(leaf.wildcards)-1] == ":ext" { + if len(leaf.wildcards) == 2 { lastone := wildcardValues[len(wildcardValues)-1] strs := strings.SplitN(lastone, ".", 2) if len(strs) == 2 { - ctx.Input.Params[":ext"] = strs[1] - } else { - ctx.Input.Params[":ext"] = "" - } - if len(wildcardValues[j:]) == 1 { - ctx.Input.Params[":path"] = strs[0] - } else { - ctx.Input.Params[":path"] = path.Join(wildcardValues[j:]...) + "/" + strs[0] + ctx.Input.SetParam(":ext", strs[1]) } + ctx.Input.SetParam(":path", path.Join(path.Join(wildcardValues[:len(wildcardValues)-1]...), strs[0])) return true - } - if len(wildcardValues) <= j { + } else if len(wildcardValues) < 2 { return false } - ctx.Input.Params[v] = wildcardValues[j] - j++ + var index int + for index = 0; index < len(leaf.wildcards)-2; index++ { + ctx.Input.SetParam(leaf.wildcards[index], wildcardValues[index]) + } + lastone := wildcardValues[len(wildcardValues)-1] + strs := strings.SplitN(lastone, ".", 2) + if len(strs) == 2 { + ctx.Input.SetParam(":ext", strs[1]) + } + ctx.Input.SetParam(":path", path.Join(path.Join(wildcardValues[index:len(wildcardValues)-1]...), strs[0])) + return true } - if len(ctx.Input.Params) != len(wildcardValues) { + // match :id + if len(leaf.wildcards) != len(wildcardValues) { return false } + for j, v := range leaf.wildcards { + ctx.Input.SetParam(v, wildcardValues[j]) + } return true } @@ -418,7 +425,7 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b } matches := leaf.regexps.FindStringSubmatch(path.Join(wildcardValues...)) for i, match := range matches[1:] { - ctx.Input.Params[leaf.wildcards[i]] = match + ctx.Input.SetParam(leaf.wildcards[i], match) } return true } diff --git a/tree_test.go b/tree_test.go index 22a7b6f1..f0923c88 100644 --- a/tree_test.go +++ b/tree_test.go @@ -45,6 +45,7 @@ func init() { routers = append(routers, testinfo{"/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}}) routers = append(routers, testinfo{"/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}}) routers = append(routers, testinfo{"/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}}) + routers = append(routers, testinfo{"/cc/:id/*", "/cc/2009/11/dd", map[string]string{":id": "2009", ":splat": "11/dd"}}) routers = append(routers, testinfo{"/ee/:year/*/ff", "/ee/2009/11/ff", map[string]string{":year": "2009", ":splat": "11"}}) routers = append(routers, testinfo{"/thumbnail/:size/uploads/*", "/thumbnail/100x100/uploads/items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg", @@ -76,14 +77,14 @@ func TestTreeRouters(t *testing.T) { ctx := context.NewContext() obj := tr.Match(r.requesturl, ctx) if obj == nil || obj.(string) != "astaxie" { - t.Fatal(r.url + " can't get obj ") + t.Fatal(r.url+" can't get obj, Expect ", r.requesturl) } if r.params != nil { for k, v := range r.params { - if vv, ok := ctx.Input.Params[k]; !ok { + if vv := ctx.Input.Param(k); vv != v { + t.Fatal("The Rule: " + r.url + "\nThe RequestURL:" + r.requesturl + "\nThe Key is " + k + ", The Value should be: " + v + ", but get: " + vv) + } else if vv == "" && v != "" { 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) } } } @@ -101,10 +102,10 @@ func TestAddTree(t *testing.T) { if obj == nil || obj.(string) != "astaxie" { t.Fatal("/v1/zl/shop/:id/account can't get obj ") } - if len(ctx.Input.Params) == 0 { + if ctx.Input.ParamsLen() == 0 { t.Fatal("get param error") } - if ctx.Input.Params[":id"] != "123" { + if ctx.Input.Param(":id") != "123" { t.Fatal("get :id param error") } ctx.Input.Reset(ctx) @@ -112,10 +113,10 @@ func TestAddTree(t *testing.T) { if obj == nil || obj.(string) != "astaxie" { t.Fatal("/v1/zl//shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ") } - if len(ctx.Input.Params) == 0 { + if ctx.Input.ParamsLen() == 0 { t.Fatal("get param error") } - if ctx.Input.Params[":sd"] != "123" || ctx.Input.Params[":id"] != "1" || ctx.Input.Params[":page"] != "12" { + if ctx.Input.Param(":sd") != "123" || ctx.Input.Param(":id") != "1" || ctx.Input.Param(":page") != "12" { t.Fatal("get :sd :id :page param error") } @@ -126,10 +127,10 @@ func TestAddTree(t *testing.T) { if obj == nil || obj.(string) != "astaxie" { t.Fatal("/v1/:shopid/shop/:id/account can't get obj ") } - if len(ctx.Input.Params) == 0 { + if ctx.Input.ParamsLen() == 0 { t.Fatal("get param error") } - if ctx.Input.Params[":id"] != "123" || ctx.Input.Params[":shopid"] != "zl" { + if ctx.Input.Param(":id") != "123" || ctx.Input.Param(":shopid") != "zl" { t.Fatal("get :id :shopid param error") } ctx.Input.Reset(ctx) @@ -137,10 +138,10 @@ func TestAddTree(t *testing.T) { if obj == nil || obj.(string) != "astaxie" { t.Fatal("/v1/:shopid/shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ") } - if len(ctx.Input.Params) == 0 { + if ctx.Input.ParamsLen() == 0 { t.Fatal("get :shopid param error") } - if ctx.Input.Params[":sd"] != "123" || ctx.Input.Params[":id"] != "1" || ctx.Input.Params[":page"] != "12" || ctx.Input.Params[":shopid"] != "zl" { + if ctx.Input.Param(":sd") != "123" || ctx.Input.Param(":id") != "1" || ctx.Input.Param(":page") != "12" || ctx.Input.Param(":shopid") != "zl" { t.Fatal("get :sd :id :page :shopid param error") } } @@ -156,10 +157,10 @@ func TestAddTree2(t *testing.T) { if obj == nil || obj.(string) != "astaxie" { t.Fatal("/:version(v1|v2)/:prefix/shop/:id/account can't get obj ") } - if len(ctx.Input.Params) == 0 { + if ctx.Input.ParamsLen() == 0 { t.Fatal("get param error") } - if ctx.Input.Params[":id"] != "123" || ctx.Input.Params[":prefix"] != "zl" || ctx.Input.Params[":version"] != "v1" { + if ctx.Input.Param(":id") != "123" || ctx.Input.Param(":prefix") != "zl" || ctx.Input.Param(":version") != "v1" { t.Fatal("get :id :prefix :version param error") } } @@ -175,10 +176,10 @@ func TestAddTree3(t *testing.T) { if obj == nil || obj.(string) != "astaxie" { t.Fatal("/table/:num/shop/:sd/account can't get obj ") } - if len(ctx.Input.Params) == 0 { + if ctx.Input.ParamsLen() == 0 { t.Fatal("get param error") } - if ctx.Input.Params[":num"] != "123" || ctx.Input.Params[":sd"] != "123" { + if ctx.Input.Param(":num") != "123" || ctx.Input.Param(":sd") != "123" { t.Fatal("get :num :sd param error") } ctx.Input.Reset(ctx) @@ -199,10 +200,12 @@ func TestAddTree4(t *testing.T) { if obj == nil || obj.(string) != "astaxie" { t.Fatal("/:info:int/:num/:id/shop/:sd/:account can't get obj ") } - if len(ctx.Input.Params) == 0 { + if ctx.Input.ParamsLen() == 0 { t.Fatal("get param error") } - 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" { + if ctx.Input.Param(":info") != "12" || ctx.Input.Param(":num") != "123" || + ctx.Input.Param(":id") != "456" || ctx.Input.Param(":sd") != "123" || + ctx.Input.Param(":account") != "account" { t.Fatal("get :info :num :id :sd :account param error") } ctx.Input.Reset(ctx)