@@ -414,6 +414,70 @@ func TestTreeRegexMatchWholeParam(t *testing.T) {
414414 }
415415}
416416
417+ func TestTreePathParam (t * testing.T ) {
418+ hPath := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {})
419+ hPathNonGreedy := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {})
420+ hPathOne := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {})
421+ hPathOneNonGreedy := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {})
422+ hSingle := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {})
423+ hFiles := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {})
424+
425+ tr := & node {}
426+ tr .InsertRoute (mGET , "/foo/bar/{other-stuff:*}/fizz/buzz" , hPath )
427+ tr .InsertRoute (mGET , "/foo/bar/{other-stuff}/fizz/buzz" , hSingle )
428+ tr .InsertRoute (mGET , "/files/{path:*}" , hFiles )
429+ tr .InsertRoute (mGET , "/plus/{path:+}/tail" , hPathOne )
430+ tr .InsertRoute (mGET , "/greedy/{path:*}/x/*" , hPath )
431+ tr .InsertRoute (mGET , "/nongreedy/{path:*?}/x/*" , hPathNonGreedy )
432+ tr .InsertRoute (mGET , "/plusgreedy/{path:+}/x/*" , hPathOne )
433+ tr .InsertRoute (mGET , "/plusnongreedy/{path:+?}/x/*" , hPathOneNonGreedy )
434+
435+ tests := []struct {
436+ r string
437+ h http.Handler
438+ k []string
439+ v []string
440+ }{
441+ {r : "/foo/bar/one/two/three/fizz/buzz" , h : hPath , k : []string {"other-stuff" }, v : []string {"one/two/three" }},
442+ {r : "/foo/bar/one/fizz/buzz" , h : hSingle , k : []string {"other-stuff" }, v : []string {"one" }},
443+ {r : "/foo/bar/fizz/buzz" , h : hPath , k : []string {"other-stuff" }, v : []string {"" }},
444+ {r : "/files/a/b/c" , h : hFiles , k : []string {"path" }, v : []string {"a/b/c" }},
445+ {r : "/files/" , h : hFiles , k : []string {"path" }, v : []string {"" }},
446+ {r : "/plus/a/tail" , h : hPathOne , k : []string {"path" }, v : []string {"a" }},
447+ {r : "/plus/a/b/tail" , h : hPathOne , k : []string {"path" }, v : []string {"a/b" }},
448+ {r : "/plus/tail" , h : nil , k : []string {}, v : []string {}},
449+ {r : "/plus//tail" , h : nil , k : []string {}, v : []string {}},
450+ {r : "/greedy/a/x/b/x/c" , h : hPath , k : []string {"path" , "*" }, v : []string {"a/x/b" , "c" }},
451+ {r : "/nongreedy/a/x/b/x/c" , h : hPathNonGreedy , k : []string {"path" , "*" }, v : []string {"a" , "b/x/c" }},
452+ {r : "/plusgreedy/a/x/b/x/c" , h : hPathOne , k : []string {"path" , "*" }, v : []string {"a/x/b" , "c" }},
453+ {r : "/plusnongreedy/a/x/b/x/c" , h : hPathOneNonGreedy , k : []string {"path" , "*" }, v : []string {"a" , "b/x/c" }},
454+ }
455+
456+ for i , tt := range tests {
457+ rctx := NewRouteContext ()
458+
459+ _ , handlers , _ := tr .FindRoute (rctx , mGET , tt .r )
460+
461+ var handler http.Handler
462+ if methodHandler , ok := handlers [mGET ]; ok {
463+ handler = methodHandler .handler
464+ }
465+
466+ paramKeys := rctx .routeParams .Keys
467+ paramValues := rctx .routeParams .Values
468+
469+ if fmt .Sprintf ("%v" , tt .h ) != fmt .Sprintf ("%v" , handler ) {
470+ t .Errorf ("input [%d]: find '%s' expecting handler:%v , got:%v" , i , tt .r , tt .h , handler )
471+ }
472+ if ! stringSliceEqual (tt .k , paramKeys ) {
473+ t .Errorf ("input [%d]: find '%s' expecting paramKeys:(%d)%v , got:(%d)%v" , i , tt .r , len (tt .k ), tt .k , len (paramKeys ), paramKeys )
474+ }
475+ if ! stringSliceEqual (tt .v , paramValues ) {
476+ t .Errorf ("input [%d]: find '%s' expecting paramValues:(%d)%v , got:(%d)%v" , i , tt .r , len (tt .v ), tt .v , len (paramValues ), paramValues )
477+ }
478+ }
479+ }
480+
417481func TestTreeFindPattern (t * testing.T ) {
418482 hStub1 := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {})
419483 hStub2 := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {})
@@ -423,6 +487,8 @@ func TestTreeFindPattern(t *testing.T) {
423487 tr .InsertRoute (mGET , "/pages/*" , hStub1 )
424488 tr .InsertRoute (mGET , "/articles/{id}/*" , hStub2 )
425489 tr .InsertRoute (mGET , "/articles/{slug}/{uid}/*" , hStub3 )
490+ tr .InsertRoute (mGET , "/files/{path:*}/info" , hStub1 )
491+ tr .InsertRoute (mGET , "/assets/{path:+?}/info" , hStub1 )
426492
427493 if tr .findPattern ("/pages" ) != false {
428494 t .Errorf ("find /pages failed" )
@@ -442,6 +508,12 @@ func TestTreeFindPattern(t *testing.T) {
442508 if tr .findPattern ("/articles/{slug}/{uid}/*" ) == false {
443509 t .Errorf ("find /articles/{slug}/{uid}/* failed" )
444510 }
511+ if tr .findPattern ("/files/{name:*}/info" ) == false {
512+ t .Errorf ("find /files/{name:*}/info failed" )
513+ }
514+ if tr .findPattern ("/assets/{name:+?}/info" ) == false {
515+ t .Errorf ("find /assets/{name:+?}/info failed" )
516+ }
445517}
446518
447519func debugPrintTree (parent int , i int , n * node , label byte ) bool {
0 commit comments