From 5ffc7911cd903926c269d816e7a90a25ad7003fa Mon Sep 17 00:00:00 2001 From: kataras Date: Thu, 24 Aug 2017 15:40:06 +0300 Subject: [PATCH] Add a TODO on the latest HISTORY.md entry Also disable version updater on Iris benchmark source code files. It may runs ever faster than before if you started the benchmarks immediately after the banner :+1: Former-commit-id: a55dc1e0b658d7386229c32ba6953b1ea60f2872 --- HISTORY.md | 27 +++++++++++++++++- _benchmarks/iris-mvc-templates/main.go | 4 ++- _benchmarks/iris-mvc/main.go | 5 +++- _benchmarks/iris-sessions/main.go | 4 ++- _benchmarks/iris/main.go | 5 +++- context/route.go | 6 ++++ core/router/api_builder.go | 4 +-- core/router/party.go | 4 +-- core/router/route.go | 18 ++++++++++++ mvc/controller.go | 39 +++++++++++++++++++++++--- 10 files changed, 103 insertions(+), 13 deletions(-) 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()