diff --git a/adaptors/gorillamux/gorillamux_test.go b/adaptors/gorillamux/gorillamux_test.go new file mode 100644 index 00000000..d2908dc2 --- /dev/null +++ b/adaptors/gorillamux/gorillamux_test.go @@ -0,0 +1,22 @@ +package gorillamux_test + +import ( + "testing" + + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/gorillamux" +) + +func TestRouteURLPath(t *testing.T) { + app := iris.New() + app.Adapt(gorillamux.New()) + + app.None("/profile/{user_id}/{ref}/{anything:.*}", nil).ChangeName("profile") + app.Boot() + + expected := "/profile/42/iris-go/something" + + if got := app.Path("profile", "user_id", 42, "ref", "iris-go", "anything", "something"); got != expected { + t.Fatalf("httprouter's reverse routing 'URLPath' error: expected %s but got %s", expected, got) + } +} diff --git a/adaptors/httprouter/httprouter.go b/adaptors/httprouter/httprouter.go index aed3a1e4..14e99d80 100644 --- a/adaptors/httprouter/httprouter.go +++ b/adaptors/httprouter/httprouter.go @@ -25,6 +25,7 @@ package httprouter // } import ( + "fmt" "net/http" "strings" @@ -461,6 +462,40 @@ type ( } ) +// path = "/api/users/:id" +// return "/api/users/%v" +// +// path = "/files/*file" +// return /files/%v +// +// path = "/:username/messages/:messageid" +// return "/%v/messages/%v" +func formatPath(path string) string { + n1Len := strings.Count(path, ":") + isMatchEverything := len(path) > 0 && path[len(path)-1] == matchEverythingByte + if n1Len == 0 && !isMatchEverything { + // its a static + return path + } + if n1Len == 0 && isMatchEverything { + //if we have something like: /mypath/anything/* -> /mypatch/anything/%v + return path[0:len(path)-2] + "%v" + + } + + splittedN1 := strings.Split(path, "/") + + for _, v := range splittedN1 { + if len(v) > 0 { + if v[0] == ':' || v[0] == matchEverythingByte { + path = strings.Replace(path, v, "%v", -1) // n1Len, but let it we don't care about performance here. + } + } + } + + return path +} + // New returns a new iris' policy to create and attach the router. // It's based on the julienschmidt/httprouter with more features and some iris-relative performance tips: // subdomains(wildcard/dynamic and static) and faster parameters set (use of the already-created context's values) @@ -497,55 +532,37 @@ func New() iris.Policies { WildcardPath: func(path string, paramName string) string { return path + slash + matchEverythingString + paramName }, + // path = "/api/users/:id", args = ["42"] + // return "/api/users/42" + // + // path = "/files/*file", args = ["mydir","myfile.zip"] + // return /files/mydir/myfile.zip + // + // path = "/:username/messages/:messageid", args = ["kataras","42"] + // return "/kataras/messages/42" + // + // This policy is used for reverse routing, + // see iris.Path/URL and ~/adaptors/view/ {{ url }} {{ urlpath }} + URLPath: func(r iris.RouteInfo, args ...string) string { + rpath := r.Path() + formattedPath := formatPath(rpath) - // URLPath: func(r iris.RouteInfo, args ...string) string { - // argsLen := len(args) - // - // // we have named parameters but arguments not given - // if argsLen == 0 && r.formattedParts > 0 { - // return "" - // } else if argsLen == 0 && r.formattedParts == 0 { - // // it's static then just return the path - // return r.path - // } - // - // // we have arguments but they are much more than the named parameters - // - // // 1 check if we have /*, if yes then join all arguments to one as path and pass that as parameter - // if argsLen > r.formattedParts { - // if r.path[len(r.path)-1] == matchEverythingByte { - // // we have to convert each argument to a string in this case - // - // argsString := make([]string, argsLen, argsLen) - // - // for i, v := range args { - // if s, ok := v.(string); ok { - // argsString[i] = s - // } else if num, ok := v.(int); ok { - // argsString[i] = strconv.Itoa(num) - // } else if b, ok := v.(bool); ok { - // argsString[i] = strconv.FormatBool(b) - // } else if arr, ok := v.([]string); ok { - // if len(arr) > 0 { - // argsString[i] = arr[0] - // argsString = append(argsString, arr[1:]...) - // } - // } - // } - // - // parameter := strings.Join(argsString, slash) - // result := fmt.Sprintf(r.formattedPath, parameter) - // return result - // } - // // 2 if !1 return false - // return "" - // } - // - // arguments := joinPathArguments(args...) - // - // return fmt.Sprintf(r.formattedPath, arguments...) - // }, + if rpath == formattedPath { + // static, no need to pass args + return rpath + } + // check if we have /*, if yes then join all arguments to one as path and pass that as parameter + if formattedPath != rpath && rpath[len(rpath)-1] == matchEverythingByte { + parameter := strings.Join(args, slash) + return fmt.Sprintf(formattedPath, parameter) + } + // else return the formattedPath with its args + for _, s := range args { + formattedPath = strings.Replace(formattedPath, "%v", s, 1) + } + return formattedPath + }, }, RouterBuilderPolicy: func(repo iris.RouteRepository, context iris.ContextPool) http.Handler { fatalErr := false diff --git a/adaptors/httprouter/httprouter_test.go b/adaptors/httprouter/httprouter_test.go index 5cec08ca..e9e403f5 100644 --- a/adaptors/httprouter/httprouter_test.go +++ b/adaptors/httprouter/httprouter_test.go @@ -284,3 +284,17 @@ func TestMuxCustomErrors(t *testing.T) { Status(r.Status).Body().Equal(r.Body) } } + +func TestRouteURLPath(t *testing.T) { + app := iris.New() + app.Adapt(httprouter.New()) + + app.None("/profile/:user_id/:ref/*anything", nil).ChangeName("profile") + app.Boot() + + expected := "/profile/42/iris-go/something" + + if got := app.Path("profile", 42, "iris-go", "something"); got != expected { + t.Fatalf("httprouter's reverse routing 'URLPath' error: expected %s but got %s", expected, got) + } +} diff --git a/policy_test.go b/policy_test.go index 33d77fcc..b52b94b8 100644 --- a/policy_test.go +++ b/policy_test.go @@ -121,7 +121,7 @@ type testNativeRoute struct { status int } -func TestRouterPolicyAdaptor(t *testing.T) { +func TestNativeRouterPolicyAdaptor(t *testing.T) { expectedWrongMethodStatus := StatusNotFound app := New(Configuration{FireMethodNotAllowed: true}) app.Adapt(newTestNativeRouter()) @@ -166,9 +166,9 @@ func TestRouterPolicyAdaptor(t *testing.T) { }).ChangeName("profile") e := httptest.New(app, t) - expected := "/profile/?user_id=42&ref=iris-go&something=anything" + expected := "/profile/?user_id=42&ref=iris-go&anything=something" - if got := app.Path("profile", "user_id", 42, "ref", "iris-go", "something", "anything"); got != expected { + if got := app.Path("profile", "user_id", 42, "ref", "iris-go", "anything", "something"); got != expected { t.Fatalf("URLPath expected %s but got %s", expected, got) }