diff --git a/HISTORY.md b/HISTORY.md index 3c99a4c3..d2fd67cd 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -38,11 +38,36 @@ type MyController struct { } func (c *MyController) Get(){ - _ = c.Route.Name() // same as `c.Ctx.GetCurrentRoute().Name()`. + _ = c.Route().Name() // same as `c.Ctx.GetCurrentRoute().Name()`. // [...] } ``` +**Updated: 24 August 2017** + +This evening, on the next version 8.3.5: + +Able to pre-calculate, register and map different (relative) paths inside a single controller +with zero performance cost. + +Meaning that in the future you will be able to use something like these: + +If `app.Controller("/user", new(user.Controller))` + +- `func(c *Controller) Get()` - `GET:/user` , as usual. +- `func(c *Controller) Post()` - `POST:/user`, as usual. +- `func(c *Controller) GetLogin()` - `GET:/user/login` +- `func(c *Controller) PostLogin()` - `POST:/user/login` +- `func(c *Controller) GetProfileFollowers()` - `GET:/user/profile/followers` +- `func(c *Controller) PostProfileFollowers()` - `POST:/user/profile/followers` +- `func(c *Controller) GetBy()` - `GET:/user/{param}` +- `func(c *Controller) GetByName(name string)` - `GET:/user/{name}` +- `func(c *Controller) PostByName(name string)` - `POST:/user/{name}` +- `func(c *Controller) GetByID(id int64 || int)` - `GET:/user/{id:int}` +- `func(c *Controller) PostByID(id int64 || int)` - `POST:/user/{id:int}` + +Watch and stay tuned my friends. + # We, 23 August 2017 | v8.3.3 Better debug messages when using MVC. diff --git a/_benchmarks/iris-mvc-templates/main.go b/_benchmarks/iris-mvc-templates/main.go index effd9c3e..5c1dd7c8 100644 --- a/_benchmarks/iris-mvc-templates/main.go +++ b/_benchmarks/iris-mvc-templates/main.go @@ -22,7 +22,9 @@ func main() { app.Controller("/about", new(controllers.AboutController)) app.Controller("/contact", new(controllers.ContactController)) - app.Run(iris.Addr(":5000")) + // 24 August 2017: Iris has a built'n version updater but we don't need it + // when benchmarking... + app.Run(iris.Addr(":5000"), iris.WithoutVersionChecker) } func configure(app *iris.Application) { diff --git a/_benchmarks/iris-mvc/main.go b/_benchmarks/iris-mvc/main.go index 5d020110..92e03b59 100644 --- a/_benchmarks/iris-mvc/main.go +++ b/_benchmarks/iris-mvc/main.go @@ -8,5 +8,8 @@ import ( func main() { app := iris.New() app.Controller("/api/values/{id}", new(controllers.ValuesController)) - app.Run(iris.Addr(":5000")) + + // 24 August 2017: Iris has a built'n version updater but we don't need it + // when benchmarking... + app.Run(iris.Addr(":5000"), iris.WithoutVersionChecker) } diff --git a/_benchmarks/iris-sessions/main.go b/_benchmarks/iris-sessions/main.go index d5a34062..956cad0d 100644 --- a/_benchmarks/iris-sessions/main.go +++ b/_benchmarks/iris-sessions/main.go @@ -24,7 +24,9 @@ func main() { app.Delete("/del", delHandler) */ - app.Run(iris.Addr(":5000")) + // 24 August 2017: Iris has a built'n version updater but we don't need it + // when benchmarking... + app.Run(iris.Addr(":5000"), iris.WithoutVersionChecker) } // Set and Get diff --git a/_benchmarks/iris/main.go b/_benchmarks/iris/main.go index a8e296a9..d9ee27de 100644 --- a/_benchmarks/iris/main.go +++ b/_benchmarks/iris/main.go @@ -10,5 +10,8 @@ func main() { app.Get("/api/values/{id}", func(ctx context.Context) { ctx.WriteString("value") }) - app.Run(iris.Addr(":5000")) + + // 24 August 2017: Iris has a built'n version updater but we don't need it + // when benchmarking... + app.Run(iris.Addr(":5000"), iris.WithoutVersionChecker) } diff --git a/context/route.go b/context/route.go index 5f816cc6..52f29515 100644 --- a/context/route.go +++ b/context/route.go @@ -21,6 +21,12 @@ type RouteReadOnly interface { // IsOnline returns true if the route is marked as "online" (state). IsOnline() bool + // StaticPath returns the static part of the original, registered route path. + // if /user/{id} it will return /user + // if /user/{id}/friend/{friendid:int} it will return /user too + // if /assets/{filepath:path} it will return /assets. + StaticPath() string + // ResolvePath returns the formatted path's %v replaced with the args. ResolvePath(args ...string) string } diff --git a/core/router/api_builder.go b/core/router/api_builder.go index 376e8429..e53e286e 100644 --- a/core/router/api_builder.go +++ b/core/router/api_builder.go @@ -183,8 +183,8 @@ func (api *APIBuilder) Handle(method string, relativePath string, handlers ...co // app.HandleMany(iris.MethodGet, "/user /user/{id:int} /user/me", userHandler) // At the other side, with `Handle` we've had to write: // app.Handle(iris.MethodGet, "/user", userHandler) -// app.Handle(iris.MethodGet, "/user/{id:int}", userByIDHandler) -// app.Handle(iris.MethodGet, "/user/me", userMeHandler) +// app.Handle(iris.MethodGet, "/user/{id:int}", userHandler) +// app.Handle(iris.MethodGet, "/user/me", userHandler) // // This method is used behind the scenes at the `Controller` function // in order to handle more than one paths for the same controller instance. diff --git a/core/router/party.go b/core/router/party.go index a1c9ec46..86ea1d1a 100644 --- a/core/router/party.go +++ b/core/router/party.go @@ -62,8 +62,8 @@ type Party interface { // app.HandleMany(iris.MethodGet, "/user /user/{id:int} /user/me", userHandler) // At the other side, with `Handle` we've had to write: // app.Handle(iris.MethodGet, "/user", userHandler) - // app.Handle(iris.MethodGet, "/user/{id:int}", userByIDHandler) - // app.Handle(iris.MethodGet, "/user/me", userMeHandler) + // app.Handle(iris.MethodGet, "/user/{id:int}", userHandler) + // app.Handle(iris.MethodGet, "/user/me", userHandler) // // This method is used behind the scenes at the `Controller` function // in order to handle more than one paths for the same controller instance. diff --git a/core/router/route.go b/core/router/route.go index 94937021..6a2f8def 100644 --- a/core/router/route.go +++ b/core/router/route.go @@ -165,6 +165,24 @@ func formatPath(path string) string { return path } +// StaticPath returns the static part of the original, registered route path. +// if /user/{id} it will return /user +// if /user/{id}/friend/{friendid:int} it will return /user too +// if /assets/{filepath:path} it will return /assets. +func (r Route) StaticPath() string { + src := r.tmpl.Src + bidx := strings.IndexByte(src, '{') + if bidx == -1 || len(src) <= bidx { + return src // no dynamic part found + } + if bidx == 0 { // found at first index, + // but never happens because of the prepended slash + return "/" + } + + return src[:bidx] +} + // ResolvePath returns the formatted path's %v replaced with the args. func (r Route) ResolvePath(args ...string) string { rpath, formattedPath := r.Path, r.FormattedPath diff --git a/mvc/controller.go b/mvc/controller.go index be5537e8..c8763070 100644 --- a/mvc/controller.go +++ b/mvc/controller.go @@ -65,8 +65,8 @@ type Controller struct { // Name contains the current controller's full name. Name string - // Route is the current request context's route. - Route context.RouteReadOnly + // currentRoute is the current request context's route. + currentRoute context.RouteReadOnly // contains the `Name` as different words, all lowercase, // without the "Controller" suffix if exists. @@ -125,6 +125,14 @@ func (c *Controller) getNameWords() []string { return c.nameAsWords } +// Route returns the current request controller's context read-only access route. +func (c *Controller) Route() context.RouteReadOnly { + if c.currentRoute == nil { + c.currentRoute = c.Ctx.GetCurrentRoute() + } + return c.currentRoute +} + const slashStr = "/" // RelPath tries to return the controller's name @@ -150,11 +158,35 @@ func (c *Controller) RelPath() string { } // [1:]to ellimuate the prefixes like "//" // request path has always "/" - rel = strings.Replace(c.Ctx.Path()[1:], rel, "", 1) + rel = strings.Replace(reqPath[1:], rel, "", 1) if rel == "" { rel = slashStr } c.relPath = rel + // this will return any dynamic path after the static one + // or a a slash "/": + // + // reqPath := c.Ctx.Path() + // if len(reqPath) == 0 { + // // it never come here + // // but to protect ourselves just return an empty slash. + // return slashStr + // } + // var routeVParams []string + // c.Params.Visit(func(key string, value string) { + // routeVParams = append(routeVParams, value) + // }) + + // rel := c.Route().StaticPath() + // println(rel) + // // [1:]to ellimuate the prefixes like "//" + // // request path has always "/" + // rel = strings.Replace(reqPath, rel[1:], "", 1) + // println(rel) + // if rel == "" { + // rel = slashStr + // } + // c.relPath = rel } return c.relPath @@ -182,7 +214,6 @@ func (c *Controller) RelTmpl() string { // It's called internally. // End-Developer can ovverride it but it still MUST be called. func (c *Controller) BeginRequest(ctx context.Context) { - c.Route = ctx.GetCurrentRoute() // path and path params c.Path = ctx.Path() c.Params = ctx.Params()