v3 (feature): new Route method (#2065)

* 🎨 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 <efectn@protonmail.com>
pull/2130/head
Jinquan Wang 2022-09-18 17:35:57 +08:00 committed by GitHub
parent 1a7f7ed8a9
commit 093882cfdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 167 additions and 53 deletions

14
app.go
View File

@ -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.

View File

@ -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) {

View File

@ -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
}

128
register.go Normal file
View File

@ -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
}

View File

@ -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