From f0e55c213fa52497c14526c0204ffae8b7f74d0c Mon Sep 17 00:00:00 2001 From: Apoorv Date: Sun, 6 Mar 2022 12:05:59 +0530 Subject: [PATCH] feat: group interface (#52) Co-authored-by: ToTu-Dev <75479355+ToTu-Dev@users.noreply.github.com> --- _examples/group/group.go | 11 + _examples/rtr/main.go | 12 +- .../{auth/test2.go => test_routes/test.go} | 2 +- _examples/start.go | 2 + group.go | 114 ++++++++++ minima.go | 13 ++ mux.go | 196 ------------------ router.go | 5 +- tree.go | 2 +- 9 files changed, 149 insertions(+), 208 deletions(-) create mode 100644 _examples/group/group.go rename _examples/rtr/{auth/test2.go => test_routes/test.go} (98%) create mode 100644 group.go delete mode 100644 mux.go diff --git a/_examples/group/group.go b/_examples/group/group.go new file mode 100644 index 0000000..f70597a --- /dev/null +++ b/_examples/group/group.go @@ -0,0 +1,11 @@ +package group + +import "github.com/gominima/minima" + +func RouteGroup() *minima.Group { + grp := minima.NewGroup("/v1") + grp.Get("/auth", func(res *minima.Response, req *minima.Request) { + res.Send("auth") + }) + return grp +} \ No newline at end of file diff --git a/_examples/rtr/main.go b/_examples/rtr/main.go index d00ed73..9a677bd 100644 --- a/_examples/rtr/main.go +++ b/_examples/rtr/main.go @@ -2,7 +2,7 @@ package rtr import ( "github.com/gominima/minima" - "github.com/gominima/minima/_examples/rtr/auth" + "github.com/gominima/minima/_examples/rtr/test_routes" ) func SimpleTest() minima.Handler { @@ -13,10 +13,10 @@ func SimpleTest() minima.Handler { func Router() *minima.Router { rt := minima.NewRouter() - rt.Get("/test/one", auth.SimpleTests()) - rt.Get("/test/two", auth.SimpleTests1()) - rt.Get("/test/three", auth.SimpleTests2()) - rt.Get("/test/four", auth.SimpleTests3()) - rt.Get("/test/last", auth.SimpleTests4()) + rt.Get("/test/one", test.SimpleTests()) + rt.Get("/test/two", test.SimpleTests1()) + rt.Get("/test/three", test.SimpleTests2()) + rt.Get("/test/four", test.SimpleTests3()) + rt.Get("/test/last", test.SimpleTests4()) return rt } \ No newline at end of file diff --git a/_examples/rtr/auth/test2.go b/_examples/rtr/test_routes/test.go similarity index 98% rename from _examples/rtr/auth/test2.go rename to _examples/rtr/test_routes/test.go index d00ed82..17780f4 100644 --- a/_examples/rtr/auth/test2.go +++ b/_examples/rtr/test_routes/test.go @@ -1,4 +1,4 @@ -package auth +package test import "github.com/gominima/minima" func SimpleTests() minima.Handler { diff --git a/_examples/start.go b/_examples/start.go index 36a2a3d..d3395cd 100644 --- a/_examples/start.go +++ b/_examples/start.go @@ -31,6 +31,7 @@ SOFTWARE. import ( "fmt" "github.com/gominima/minima" + "github.com/gominima/minima/_examples/group" "github.com/gominima/minima/_examples/rtr" "net/http" ) @@ -39,6 +40,7 @@ func main() { app := minima.New() app.UseRaw(SimpleTest()) app.UseRouter(rtr.Router()) + app.UseGroup(group.RouteGroup()) app.Get("/", func(res *minima.Response, req *minima.Request) { res.Send("Hello") res.Send(req.Query("name")) diff --git a/group.go b/group.go new file mode 100644 index 0000000..4802c7d --- /dev/null +++ b/group.go @@ -0,0 +1,114 @@ +package minima + +/** + * @info The minima group structure + * @property {[]cacheroute} [route] The array of cached routes + * @property {[string} [prefix] The group prefix + */ +type Group struct { + route []*cacheRoute + prefix string +} + +/** + * @info Creates a new minima group + * @return {Group} + */ +func NewGroup(prefix string) *Group { + return &Group{ + route: make([]*cacheRoute, 0), + prefix: prefix, + } +} + +func (g *Group) register(method string, path string, handler Handler) { + g.route = append(g.route, &cacheRoute{ + method: method, + path: g.prefix + path, + handler: handler, + }) +} + +/** + * @info Adds route with Get method + * @param {string} [path] The route path + * @param {...Handler} [handler] The handler for the given route + * @returns {*Router} + */ +func (g *Group) Get(path string, handler Handler) *Group { + g.register("GET", path, handler) + return g +} + +/** + * @info Adds route with Post method + * @param {string} [path] The route path + * @param {...Handler} [handler] The handler for the given route + * @returns {*Group} + */ +func (g *Group) Post(path string, handler Handler) *Group { + g.register("POST", path, handler) + return g +} + +/** + * @info Adds route with Put method + * @param {string} [path] The route path + * @param {...Handler} [handler] The handler for the given route + * @returns {*Group} + */ +func (g *Group) Put(path string, handler Handler) *Group { + g.register("PUT", path, handler) + return g +} + +/** + * @info Adds route with Patch method + * @param {string} [path] The route path + * @param {...Handler} [handler] The handler for the given route + * @returns {*Group} + */ +func (g *Group) Patch(path string, handler Handler) { + g.register("PATCH", path, handler) +} + +/** + * @info Adds route with Options method + * @param {string} [path] The route path + * @param {...Handler} [handler] The handler for the given route + * @returns {*Group} + */ +func (g *Group) Options(path string, handler Handler) *Group { + g.register("OPTIONS", path, handler) + return g +} + +/** + * @info Adds route with Head method + * @param {string} [path] The route path + * @param {...Handler} [handler] The handler for the given route + * @returns {*Group} + */ +func (g *Group) Head(path string, handler Handler) *Group { + g.register("HEAD", path, handler) + return g +} + +/** + * @info Adds route with Delete method + * @param {string} [path] The route path + * @param {...Handler} [handler] The handler for the given route + * @returns {*Group} + */ +func (g *Group) Delete(path string, handler Handler) *Group { + g.register("DELETE", path, handler) + return g +} + +/** + * @info Returns all routes for the group + * @return {[]cachRoute} + */ +func (g *Group) GetGroupRoutes() []*cacheRoute { + return g.route +} diff --git a/minima.go b/minima.go index 2911a30..64bd39e 100644 --- a/minima.go +++ b/minima.go @@ -291,3 +291,16 @@ func (m *Minima) Use(handler Handler) *Minima { m.router.use(build(handler, nil)) return m } + +/** + * @info Injects minima group to main router stack + * @param {Group} [grp] The minima group to append + * @returns {} + */ +func (m *Minima) UseGroup(grp *Group) *Minima { + for _, v := range grp.GetGroupRoutes() { + fmt.Print(v.method) + m.router.routes[v.method].InsertNode(v.path, v.handler) + } + return m +} diff --git a/mux.go b/mux.go deleted file mode 100644 index 41904b5..0000000 --- a/mux.go +++ /dev/null @@ -1,196 +0,0 @@ -package minima - -/** -* Minima is a free and open source software under Mit license - -Copyright (c) 2021 gominima - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -* Authors @apoorvcodes @megatank58 -* Maintainers @Panquesito7 @savioxavier @Shubhaankar-Sharma @apoorvcodes @megatank58 -* Thank you for showing interest in minima and for this beautiful community -*/ - -import ( - "strings" -) - -/** - * @info The Param structure - * @property {string} [name] The name of the param - * @property {bool} [fixed] Whether the param is fixed or not - */ -type param struct { - name string - fixed bool -} - -/** - * @info The Route structure - * @property {string} [prefix] The prefix of the route - * @property {[]param} [partnames] The route paths split into parts - * @property {Handler} [function] The handler to be used - */ -type Route struct { - prefix string - partNames []param - function Handler -} - -/** - * @info The Routes root structure - * @property {map[string][]Route} [roots] The map of array routes - */ -type Routes struct { - roots map[string][]Route -} - -/** - * @info Makes a new Routes instance - * @returns {*Routes} - */ -func NewRoutes() *Routes { - return &Routes{ - roots: make(map[string][]Route), - } -} - -/** - * @info Adds a new route to the routes table - * @param {string} [path] Path of the route - * @param {Handler} [handler] Handler of the route - */ -func (r *Routes) Add(path string, f Handler) { - parts := strings.Split(path, "/") - var rootParts []string - var varParts []param - var paramsFound bool - for _, p := range parts { - if strings.HasPrefix(p, ":") { - paramsFound = true - } - - if paramsFound { - if strings.HasPrefix(p, ":") { - varParts = append(varParts, param{ - name: strings.TrimPrefix(p, ":"), - fixed: false, - }) - } else { - varParts = append(varParts, param{ - name: p, - fixed: true, - }) - } - } else { - rootParts = append(rootParts, p) - } - } - - root := strings.Join(rootParts, "/") - - r.roots[root] = append(r.roots[root], Route{ - prefix: root, - partNames: varParts, - function: f, - }) -} - -/** - * @info Gets handler and params from the routes table - * @param {string} [path] Path of the route to find - * @returns {Handler, map[string]string, bool} - */ -func (r *Routes) Get(path string) (Handler, map[string]string, bool) { - var routes []Route - remaining := path - for { - var ok bool - routes, ok = r.roots[remaining] - if ok { - return matchRoutes(path, routes) - - } - - if len(remaining) < 2 { - return nil, nil, false - } - - index := strings.LastIndex(remaining, "/") - if index < 0 { - return nil, nil, false - } - - if index > 0 { - remaining = remaining[:index] - } else { - remaining = "/" - } - } -} - -/** - * @info Matches routes to the request - * @param {string} [path] Path of the request route to find - * @param {[]Route} [routes] The array of routes to match - * @returns {Handler, map[string]string, bool} - */ -func matchRoutes(path string, routes []Route) (Handler, map[string]string, bool) { -outer: - for _, r := range routes { - params := strings.Split( - strings.TrimPrefix( - strings.TrimPrefix(path, r.prefix), - "/"), - "/") - valid := cleanArray(params) - - if len(valid) == len(r.partNames) { - paramNames := make(map[string]string) - for i, p := range r.partNames { - if p.fixed { - if params[i] != p.name { - continue outer - } else { - continue - } - } - paramNames[p.name] = params[i] - } - return r.function, paramNames, true - } - } - return nil, nil, false -} - -/** - * @info Cleans the array and finds non nill values - * @param {string} [path] The array of string to slice and clean - * @returns {[]string} - */ -func cleanArray(a []string) []string { - var valid []string - for _, s := range a { - if s != "" { - valid = append(valid, s) - } - } - return valid -} diff --git a/router.go b/router.go index e4e8a0b..c200467 100644 --- a/router.go +++ b/router.go @@ -29,15 +29,12 @@ SOFTWARE. */ import ( - "fmt" + "fmt" "net/http" ) type Handler func(res *Response, req *Request) - - - /** * @info The cache routes struct * @property {string} [method] The route method diff --git a/tree.go b/tree.go index 331125b..241d915 100644 --- a/tree.go +++ b/tree.go @@ -159,7 +159,7 @@ func (tr *tree) InsertNode(key string, handler Handler) { priority: 1, }, }) - + tr.len++ tr.size += len(key) return