From 093882cfdf3948e2c250830e135f3076a79cdc4a Mon Sep 17 00:00:00 2001 From: Jinquan Wang <35188480+wangjq4214@users.noreply.github.com> Date: Sun, 18 Sep 2022 17:35:57 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20v3=20(feature):=20new=20Route=20met?= =?UTF-8?q?hod=20(#2065)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🎨 perf: change name to add new feature * ✨ feat add route * 🎨 perf: rollback name * 🎨 perf: change file name * fix: fix errors caused by register * 🎨 perf: change filed to private and change comment * feat: interface is better * 🎨 perf: change type name * deeper tests Co-authored-by: Muhammed Efe Γ‡etin --- app.go | 14 ++---- app_test.go | 64 +++++++++++++------------- group.go | 12 ++--- register.go | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++ router.go | 2 +- 5 files changed, 167 insertions(+), 53 deletions(-) create mode 100644 register.go diff --git a/app.go b/app.go index 861c321b..708b16a1 100644 --- a/app.go +++ b/app.go @@ -748,17 +748,11 @@ func (app *App) Group(prefix string, handlers ...Handler) Router { // Route is used to define routes with a common prefix inside the common function. // Uses Group method to define new sub-router. -func (app *App) Route(prefix string, fn func(router Router), name ...string) Router { - // Create new group - group := app.Group(prefix) - if len(name) > 0 { - group.Name(name[0]) - } +func (app *App) Route(path string) Register { + // Create new route + route := &Registering{app: app, path: path} - // Define routes - fn(group) - - return group + return route } // Error makes it compatible with the `error` interface. diff --git a/app_test.go b/app_test.go index 1e145973..b6a32605 100644 --- a/app_test.go +++ b/app_test.go @@ -1030,48 +1030,46 @@ func Test_App_Route(t *testing.T) { app := New() - grp := app.Route("/test", func(grp Router) { - grp.Get("/", dummyHandler) - grp.Get("/:demo?", dummyHandler) - grp.Connect("/CONNECT", dummyHandler) - grp.Put("/PUT", dummyHandler) - grp.Post("/POST", dummyHandler) - grp.Delete("/DELETE", dummyHandler) - grp.Head("/HEAD", dummyHandler) - grp.Patch("/PATCH", dummyHandler) - grp.Options("/OPTIONS", dummyHandler) - grp.Trace("/TRACE", dummyHandler) - grp.All("/ALL", dummyHandler) - grp.Use(dummyHandler) - grp.Use("/USE", dummyHandler) - }) + register := app.Route("/test"). + Get(dummyHandler). + Post(dummyHandler). + Put(dummyHandler). + Delete(dummyHandler). + Connect(dummyHandler). + Options(dummyHandler). + Trace(dummyHandler). + Patch(dummyHandler) testStatus200(t, app, "/test", MethodGet) - testStatus200(t, app, "/test/john", MethodGet) - testStatus200(t, app, "/test/CONNECT", MethodConnect) - testStatus200(t, app, "/test/PUT", MethodPut) - testStatus200(t, app, "/test/POST", MethodPost) - testStatus200(t, app, "/test/DELETE", MethodDelete) - testStatus200(t, app, "/test/HEAD", MethodHead) - testStatus200(t, app, "/test/PATCH", MethodPatch) - testStatus200(t, app, "/test/OPTIONS", MethodOptions) - testStatus200(t, app, "/test/TRACE", MethodTrace) - testStatus200(t, app, "/test/ALL", MethodPost) - testStatus200(t, app, "/test/oke", MethodGet) - testStatus200(t, app, "/test/USE/oke", MethodGet) + testStatus200(t, app, "/test", MethodHead) + testStatus200(t, app, "/test", MethodPost) + testStatus200(t, app, "/test", MethodPut) + testStatus200(t, app, "/test", MethodDelete) + testStatus200(t, app, "/test", MethodConnect) + testStatus200(t, app, "/test", MethodOptions) + testStatus200(t, app, "/test", MethodTrace) + testStatus200(t, app, "/test", MethodPatch) - grp.Route("/v1", func(grp Router) { - grp.Post("/", dummyHandler) - grp.Get("/users", dummyHandler) - }) + register.Route("/v1").Get(dummyHandler).Post(dummyHandler) - resp, err := app.Test(httptest.NewRequest(MethodPost, "/test/v1/", nil)) + resp, err := app.Test(httptest.NewRequest(MethodPost, "/test/v1", nil)) require.NoError(t, err, "app.Test(req)") require.Equal(t, 200, resp.StatusCode, "Status code") - resp, err = app.Test(httptest.NewRequest(MethodGet, "/test/v1/UsErS", nil)) + resp, err = app.Test(httptest.NewRequest(MethodGet, "/test/v1", nil)) require.NoError(t, err, "app.Test(req)") require.Equal(t, 200, resp.StatusCode, "Status code") + + register.Route("/v1").Route("/v2").Route("/v3").Get(dummyHandler).Trace(dummyHandler) + + resp, err = app.Test(httptest.NewRequest(MethodTrace, "/test/v1/v2/v3", nil)) + require.NoError(t, err, "app.Test(req)") + require.Equal(t, 200, resp.StatusCode, "Status code") + + resp, err = app.Test(httptest.NewRequest(MethodGet, "/test/v1/v2/v3", nil)) + require.NoError(t, err, "app.Test(req)") + require.Equal(t, 200, resp.StatusCode, "Status code") + } func Test_App_Deep_Group(t *testing.T) { diff --git a/group.go b/group.go index 502041de..1f09eca9 100644 --- a/group.go +++ b/group.go @@ -184,15 +184,9 @@ func (grp *Group) Group(prefix string, handlers ...Handler) Router { // Route is used to define routes with a common prefix inside the common function. // Uses Group method to define new sub-router. -func (grp *Group) Route(prefix string, fn func(router Router), name ...string) Router { +func (grp *Group) Route(path string) Register { // Create new group - group := grp.Group(prefix) - if len(name) > 0 { - group.Name(name[0]) - } + register := &Registering{app: grp.app, path: getGroupPath(grp.Prefix, path)} - // Define routes - fn(group) - - return group + return register } diff --git a/register.go b/register.go new file mode 100644 index 00000000..9f0bf92d --- /dev/null +++ b/register.go @@ -0,0 +1,128 @@ +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ +// πŸ€– Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io + +package fiber + +// Register defines all router handle interface generate by Route(). +type Register interface { + All(handlers ...Handler) Register + Get(handlers ...Handler) Register + Head(handlers ...Handler) Register + Post(handlers ...Handler) Register + Put(handlers ...Handler) Register + Delete(handlers ...Handler) Register + Connect(handlers ...Handler) Register + Options(handlers ...Handler) Register + Trace(handlers ...Handler) Register + Patch(handlers ...Handler) Register + + Add(method string, handlers ...Handler) Register + + Static(root string, config ...Static) Register + + Route(path string) Register +} + +var _ (Register) = (*Registering)(nil) + +// Registering struct +type Registering struct { + app *App + + path string +} + +// All registers a middleware route that will match requests +// with the provided path which is stored in register struct. +// +// app.Route("/").All(func(c fiber.Ctx) error { +// return c.Next() +// }) +// app.Route("/api").All(func(c fiber.Ctx) error { +// return c.Next() +// }) +// app.Route("/api").All(handler, func(c fiber.Ctx) error { +// return c.Next() +// }) +// +// This method will match all HTTP verbs: GET, POST, PUT, HEAD etc... +func (r *Registering) All(handlers ...Handler) Register { + r.app.register(methodUse, r.path, handlers...) + return r +} + +// Get registers a route for GET methods that requests a representation +// of the specified resource. Requests using GET should only retrieve data. +func (r *Registering) Get(handlers ...Handler) Register { + r.app.Add(MethodHead, r.path, handlers...).Add(MethodGet, r.path, handlers...) + return r +} + +// Head registers a route for HEAD methods that asks for a response identical +// to that of a GET request, but without the response body. +func (r *Registering) Head(handlers ...Handler) Register { + return r.Add(MethodHead, handlers...) +} + +// Post registers a route for POST methods that is used to submit an entity to the +// specified resource, often causing a change in state or side effects on the server. +func (r *Registering) Post(handlers ...Handler) Register { + return r.Add(MethodPost, handlers...) +} + +// Put registers a route for PUT methods that replaces all current representations +// of the target resource with the request payload. +func (r *Registering) Put(handlers ...Handler) Register { + return r.Add(MethodPut, handlers...) +} + +// Delete registers a route for DELETE methods that deletes the specified resource. +func (r *Registering) Delete(handlers ...Handler) Register { + return r.Add(MethodDelete, handlers...) +} + +// Connect registers a route for CONNECT methods that establishes a tunnel to the +// server identified by the target resource. +func (r *Registering) Connect(handlers ...Handler) Register { + return r.Add(MethodConnect, handlers...) +} + +// Options registers a route for OPTIONS methods that is used to describe the +// communication options for the target resource. +func (r *Registering) Options(handlers ...Handler) Register { + return r.Add(MethodOptions, handlers...) +} + +// Trace registers a route for TRACE methods that performs a message loop-back +// test along the r.Path to the target resource. +func (r *Registering) Trace(handlers ...Handler) Register { + return r.Add(MethodTrace, handlers...) +} + +// Patch registers a route for PATCH methods that is used to apply partial +// modifications to a resource. +func (r *Registering) Patch(handlers ...Handler) Register { + return r.Add(MethodPatch, handlers...) +} + +// Add allows you to specify a HTTP method to register a route +func (r *Registering) Add(method string, handlers ...Handler) Register { + r.app.register(method, r.path, handlers...) + return r +} + +// Static will create a file server serving static files +func (r *Registering) Static(root string, config ...Static) Register { + r.app.registerStatic(r.path, root, config...) + return r +} + +// Route returns a new Register instance whose route path takes +// the path in the current instance as its prefix. +func (r *Registering) Route(path string) Register { + // Create new group + route := &Registering{app: r.app, path: getGroupPath(r.path, path)} + + return route +} diff --git a/router.go b/router.go index 559635b3..614ff937 100644 --- a/router.go +++ b/router.go @@ -36,7 +36,7 @@ type Router interface { Group(prefix string, handlers ...Handler) Router - Route(prefix string, fn func(router Router), name ...string) Router + Route(path string) Register Mount(prefix string, fiber *App) Router