Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸš€ Improve routing behavior #715

Merged
merged 14 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion app.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ type App struct {
mutex sync.Mutex
// Route stack divided by HTTP methods
stack [][]*Route
// Route stack divided by HTTP methods and route prefixes
treeStack []map[string][]*Route
// Amount of registered routes
routesCount int
// Amount of registered handlers
handlerCount int
// Ctx pool
Expand Down Expand Up @@ -232,7 +236,8 @@ func New(settings ...*Settings) *App {
// Create a new app
app := &App{
// Create router stack
stack: make([][]*Route, len(intMethod)),
stack: make([][]*Route, len(intMethod)),
treeStack: make([]map[string][]*Route, len(intMethod)),
// Create Ctx pool
pool: sync.Pool{
New: func() interface{} {
Expand Down Expand Up @@ -630,6 +635,7 @@ func (app *App) init() *App {
app.server.IdleTimeout = app.Settings.IdleTimeout
app.server.ReadBufferSize = app.Settings.ReadBufferSize
app.server.WriteBufferSize = app.Settings.WriteBufferSize
app.buildTree()
app.mutex.Unlock()
return app
}
Expand Down
11 changes: 11 additions & 0 deletions ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type Ctx struct {
method string // HTTP method
methodINT int // HTTP method INT equivalent
path string // Prettified HTTP path
treePath string // Path for the search in the tree
pathOriginal string // Original HTTP path
values []string // Route parameter values
err error // Contains error if passed to Next
Expand Down Expand Up @@ -90,6 +91,8 @@ func (app *App) AcquireCtx(fctx *fasthttp.RequestCtx) *Ctx {
ctx.methodINT = methodInt(ctx.method)
// Attach *fasthttp.RequestCtx to ctx
ctx.Fasthttp = fctx
// Prettify path
ctx.prettifyPath()
return ctx
}

Expand Down Expand Up @@ -646,6 +649,9 @@ func (ctx *Ctx) OriginalURL() string {
// Returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting to use the value outside the Handler.
func (ctx *Ctx) Params(key string, defaultValue ...string) string {
if key == "*" || key == "+" {
key += "1"
}
for i := range ctx.route.Params {
if len(key) != len(ctx.route.Params[i]) {
continue
Expand Down Expand Up @@ -1031,4 +1037,9 @@ func (ctx *Ctx) prettifyPath() {
if !ctx.app.Settings.StrictRouting && len(ctx.path) > 1 && ctx.path[len(ctx.path)-1] == '/' {
ctx.path = utils.TrimRight(ctx.path, '/')
}

ctx.treePath = ctx.treePath[0:0]
if len(ctx.path) >= 3 {
ctx.treePath = ctx.path[:3]
}
}
15 changes: 13 additions & 2 deletions ctx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -913,16 +913,27 @@ func Test_Ctx_Params(t *testing.T) {
app.Get("/test2/*", func(c *Ctx) {
utils.AssertEqual(t, "im/a/cookie", c.Params("*"))
})
app.Get("/test3/:optional?", func(c *Ctx) {
app.Get("/test3/*/blafasel/*", func(c *Ctx) {
utils.AssertEqual(t, "1111", c.Params("*1"))
utils.AssertEqual(t, "2222", c.Params("*2"))
utils.AssertEqual(t, "1111", c.Params("*"))
})
app.Get("/test4/:optional?", func(c *Ctx) {
utils.AssertEqual(t, "", c.Params("optional"))
})
resp, err := app.Test(httptest.NewRequest(MethodGet, "/test/john", nil))
utils.AssertEqual(t, nil, err, "app.Test(req)")
utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code")

resp, err = app.Test(httptest.NewRequest(MethodGet, "/test2/im/a/cookie", nil))
utils.AssertEqual(t, nil, err, "app.Test(req)")
utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code")
resp, err = app.Test(httptest.NewRequest(MethodGet, "/test3", nil))

resp, err = app.Test(httptest.NewRequest(MethodGet, "/test3/1111/blafasel/2222", nil))
utils.AssertEqual(t, nil, err, "app.Test(req)")
utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code")

resp, err = app.Test(httptest.NewRequest(MethodGet, "/test4", nil))
utils.AssertEqual(t, nil, err, "app.Test(req)")
utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code")
}
Expand Down
Loading