mirror of
https://github.com/gofiber/fiber.git
synced 2025-02-23 10:03:45 +00:00
Merge pull request #418 from Fenny/master
Fix partial wildcard in Static
This commit is contained in:
commit
1cd55804b7
2
app.go
2
app.go
@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
// Version of current package
|
||||
const Version = "1.10.0"
|
||||
const Version = "1.10.1"
|
||||
|
||||
// Map is a shortcut for map[string]interface{}, usefull for JSON returns
|
||||
type Map map[string]interface{}
|
||||
|
105
app_test.go
105
app_test.go
@ -88,6 +88,33 @@ func Test_App_Use_Params_Group(t *testing.T) {
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
}
|
||||
|
||||
func Test_App_Chaining(t *testing.T) {
|
||||
n := func(c *Ctx) {
|
||||
c.Next()
|
||||
}
|
||||
app := New()
|
||||
app.Use("/john", n, n, n, n, func(c *Ctx) {
|
||||
c.Status(202)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("POST", "/john", nil)
|
||||
|
||||
resp, err := app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 202, resp.StatusCode, "Status code")
|
||||
|
||||
app.Get("/test", n, n, n, n, func(c *Ctx) {
|
||||
c.Status(203)
|
||||
})
|
||||
|
||||
req = httptest.NewRequest("GET", "/test", nil)
|
||||
|
||||
resp, err = app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 203, resp.StatusCode, "Status code")
|
||||
|
||||
}
|
||||
|
||||
func Test_App_Order(t *testing.T) {
|
||||
app := New()
|
||||
|
||||
@ -176,13 +203,66 @@ func Test_App_Shutdown(t *testing.T) {
|
||||
_ = app.Shutdown()
|
||||
}
|
||||
|
||||
func Test_App_Static(t *testing.T) {
|
||||
// go test -run Test_App_Static
|
||||
func Test_App_Static_Group(t *testing.T) {
|
||||
app := New()
|
||||
|
||||
grp := app.Group("/v1")
|
||||
grp := app.Group("/v1", func(c *Ctx) {
|
||||
c.Set("Test-Header", "123")
|
||||
c.Next()
|
||||
})
|
||||
|
||||
grp.Static("/v2", ".github/auth_assign.yml")
|
||||
app.Static("/*", ".github/FUNDING.yml")
|
||||
grp.Static("/v2", "./.github/FUNDING.yml")
|
||||
|
||||
req := httptest.NewRequest("GET", "/v1/v2", nil)
|
||||
resp, err := app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
utils.AssertEqual(t, false, resp.Header.Get("Content-Length") == "")
|
||||
utils.AssertEqual(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type"))
|
||||
utils.AssertEqual(t, "123", resp.Header.Get("Test-Header"))
|
||||
|
||||
grp = app.Group("/v2")
|
||||
grp.Static("/v3*", "./.github/FUNDING.yml")
|
||||
|
||||
req = httptest.NewRequest("GET", "/v2/v3/john/doe", nil)
|
||||
resp, err = app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
utils.AssertEqual(t, false, resp.Header.Get("Content-Length") == "")
|
||||
utils.AssertEqual(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type"))
|
||||
|
||||
}
|
||||
|
||||
func Test_App_Static_Wildcard(t *testing.T) {
|
||||
app := New()
|
||||
|
||||
app.Static("*", "./.github/FUNDING.yml")
|
||||
|
||||
req := httptest.NewRequest("GET", "/yesyes/john/doe", nil)
|
||||
resp, err := app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
utils.AssertEqual(t, false, resp.Header.Get("Content-Length") == "")
|
||||
utils.AssertEqual(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type"))
|
||||
|
||||
}
|
||||
|
||||
func Test_App_Static_Prefix_Wildcard(t *testing.T) {
|
||||
app := New()
|
||||
|
||||
app.Static("/test/*", "./.github/FUNDING.yml")
|
||||
|
||||
req := httptest.NewRequest("GET", "/test/john/doe", nil)
|
||||
resp, err := app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
utils.AssertEqual(t, false, resp.Header.Get("Content-Length") == "")
|
||||
utils.AssertEqual(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type"))
|
||||
}
|
||||
|
||||
func Test_App_Static_Prefix(t *testing.T) {
|
||||
app := New()
|
||||
app.Static("/john", "./.github")
|
||||
|
||||
req := httptest.NewRequest("GET", "/john/stale.yml", nil)
|
||||
@ -190,24 +270,25 @@ func Test_App_Static(t *testing.T) {
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
utils.AssertEqual(t, false, resp.Header.Get("Content-Length") == "")
|
||||
utils.AssertEqual(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type"))
|
||||
|
||||
req = httptest.NewRequest("GET", "/yesyes/john/doe", nil)
|
||||
app.Static("/prefix", "./.github/workflows")
|
||||
|
||||
req = httptest.NewRequest("GET", "/prefix/test.yml", nil)
|
||||
resp, err = app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
utils.AssertEqual(t, false, resp.Header.Get("Content-Length") == "")
|
||||
utils.AssertEqual(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type"))
|
||||
|
||||
req = httptest.NewRequest("GET", "/john/stale.yml", nil)
|
||||
resp, err = app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
utils.AssertEqual(t, false, resp.Header.Get("Content-Length") == "")
|
||||
|
||||
req = httptest.NewRequest("GET", "/v1/v2", nil)
|
||||
app.Static("/single", "./.github/workflows/test.yml")
|
||||
|
||||
req = httptest.NewRequest("GET", "/single", nil)
|
||||
resp, err = app.Test(req)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
utils.AssertEqual(t, false, resp.Header.Get("Content-Length") == "")
|
||||
utils.AssertEqual(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type"))
|
||||
}
|
||||
|
||||
func Test_App_Group(t *testing.T) {
|
||||
|
22
ctx.go
22
ctx.go
@ -34,8 +34,8 @@ import (
|
||||
type Ctx struct {
|
||||
app *App // Reference to *App
|
||||
route *Route // Reference to *Route
|
||||
index int // Index of the current handler in the stack
|
||||
next bool // Bool to continue to the next handler
|
||||
indexRoute int // Index of the current route
|
||||
indexHandler int // Index of the current handler
|
||||
method string // HTTP method
|
||||
path string // Prettified HTTP path
|
||||
pathOriginal string // Original HTTP path
|
||||
@ -78,8 +78,9 @@ func (app *App) AcquireCtx(fctx *fasthttp.RequestCtx) *Ctx {
|
||||
ctx := app.pool.Get().(*Ctx)
|
||||
// Set app reference
|
||||
ctx.app = app
|
||||
// Set stack index
|
||||
ctx.index = -1
|
||||
// Reset route and handler index
|
||||
ctx.indexRoute = -1
|
||||
ctx.indexHandler = 0
|
||||
// Set paths
|
||||
ctx.path = getString(fctx.URI().Path())
|
||||
ctx.pathOriginal = ctx.path
|
||||
@ -577,8 +578,17 @@ func (ctx *Ctx) Next(err ...error) {
|
||||
if len(err) > 0 {
|
||||
ctx.err = err[0]
|
||||
}
|
||||
ctx.next = true
|
||||
ctx.app.next(ctx)
|
||||
|
||||
// Increment handler index
|
||||
ctx.indexHandler++
|
||||
// Did we executed all route handlers?
|
||||
if ctx.indexHandler < len(ctx.route.Handlers) {
|
||||
// Continue route stack
|
||||
ctx.route.Handlers[ctx.indexHandler](ctx)
|
||||
} else {
|
||||
// Continue handler stack
|
||||
ctx.app.next(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// OriginalURL contains the original request URL.
|
||||
|
64
router.go
64
router.go
@ -67,11 +67,11 @@ func (app *App) next(ctx *Ctx) bool {
|
||||
// Get stack length
|
||||
lenr := len(app.stack[method]) - 1
|
||||
// Loop over the route stack starting from previous index
|
||||
for ctx.index < lenr {
|
||||
// Increment stack index
|
||||
ctx.index++
|
||||
for ctx.indexRoute < lenr {
|
||||
// Increment route index
|
||||
ctx.indexRoute++
|
||||
// Get *Route
|
||||
route := app.stack[method][ctx.index]
|
||||
route := app.stack[method][ctx.indexRoute]
|
||||
// Check if it matches the request path
|
||||
match, values := route.match(ctx.path, ctx.pathOriginal)
|
||||
// No match, next route
|
||||
@ -81,17 +81,9 @@ func (app *App) next(ctx *Ctx) bool {
|
||||
// Pass route reference and param values
|
||||
ctx.route = route
|
||||
ctx.values = values
|
||||
// Loop trough all handlers
|
||||
for i := range route.Handlers {
|
||||
// Execute ctx handler
|
||||
route.Handlers[i](ctx)
|
||||
// Stop if c.Next() is not called
|
||||
if !ctx.next {
|
||||
break
|
||||
}
|
||||
// Reset next bool
|
||||
ctx.next = false
|
||||
}
|
||||
// Execute first handler of route
|
||||
ctx.indexHandler = 0
|
||||
route.Handlers[0](ctx)
|
||||
// Stop scanning the stack
|
||||
return true
|
||||
}
|
||||
@ -191,6 +183,10 @@ func (app *App) register(method, pathRaw string, handlers ...Handler) *Route {
|
||||
}
|
||||
|
||||
func (app *App) registerStatic(prefix, root string, config ...Static) *Route {
|
||||
// For security we want to restrict to the current work directory.
|
||||
if len(root) == 0 {
|
||||
root = "."
|
||||
}
|
||||
// Cannot have an empty prefix
|
||||
if prefix == "" {
|
||||
prefix = "/"
|
||||
@ -199,31 +195,26 @@ func (app *App) registerStatic(prefix, root string, config ...Static) *Route {
|
||||
if prefix[0] != '/' {
|
||||
prefix = "/" + prefix
|
||||
}
|
||||
// Match anything
|
||||
var wildcard = false
|
||||
if prefix == "*" || prefix == "/*" {
|
||||
wildcard = true
|
||||
prefix = "/"
|
||||
}
|
||||
// in case sensitive routing, all to lowercase
|
||||
if !app.Settings.CaseSensitive {
|
||||
prefix = utils.ToLower(prefix)
|
||||
}
|
||||
// For security we want to restrict to the current work directory.
|
||||
if len(root) == 0 {
|
||||
root = "."
|
||||
}
|
||||
// Strip trailing slashes from the root path
|
||||
if len(root) > 0 && root[len(root)-1] == '/' {
|
||||
root = root[:len(root)-1]
|
||||
}
|
||||
// isSlash ?
|
||||
// Is prefix a direct wildcard?
|
||||
var isStar = prefix == "/*"
|
||||
// Is prefix a root slash?
|
||||
var isRoot = prefix == "/"
|
||||
// Is prefix a partial wildcard?
|
||||
if strings.Contains(prefix, "*") {
|
||||
wildcard = true
|
||||
// /john* -> /john
|
||||
isStar = true
|
||||
prefix = strings.Split(prefix, "*")[0]
|
||||
// Fix this later
|
||||
}
|
||||
var stripper = len(prefix) - 1
|
||||
prefixLen := len(prefix)
|
||||
// Fileserver settings
|
||||
fs := &fasthttp.FS{
|
||||
Root: root,
|
||||
@ -233,7 +224,17 @@ func (app *App) registerStatic(prefix, root string, config ...Static) *Route {
|
||||
CompressedFileSuffix: ".fiber.gz",
|
||||
CacheDuration: 10 * time.Second,
|
||||
IndexNames: []string{"index.html"},
|
||||
PathRewrite: fasthttp.NewPathPrefixStripper(stripper),
|
||||
PathRewrite: func(ctx *fasthttp.RequestCtx) []byte {
|
||||
path := ctx.Path()
|
||||
if len(path) >= prefixLen {
|
||||
if isStar && getString(path[0:prefixLen]) == prefix {
|
||||
path = path[0:0]
|
||||
} else {
|
||||
path = path[prefixLen:]
|
||||
}
|
||||
}
|
||||
return append(path, '/')
|
||||
},
|
||||
PathNotFound: func(ctx *fasthttp.RequestCtx) {
|
||||
ctx.Response.SetStatusCode(404)
|
||||
},
|
||||
@ -249,10 +250,6 @@ func (app *App) registerStatic(prefix, root string, config ...Static) *Route {
|
||||
}
|
||||
fileHandler := fs.NewRequestHandler()
|
||||
handler := func(c *Ctx) {
|
||||
// Do stuff
|
||||
if wildcard {
|
||||
c.Fasthttp.Request.SetRequestURI(prefix)
|
||||
}
|
||||
// Serve file
|
||||
fileHandler(c.Fasthttp)
|
||||
// Return request if found and not forbidden
|
||||
@ -283,7 +280,6 @@ func (app *App) registerStatic(prefix, root string, config ...Static) *Route {
|
||||
app.addRoute(MethodHead, route)
|
||||
return route
|
||||
}
|
||||
|
||||
func (app *App) addRoute(method string, route *Route) {
|
||||
// Get unique HTTP method indentifier
|
||||
m := methodINT[method]
|
||||
|
@ -254,11 +254,11 @@ func Benchmark_Router_Next(b *testing.B) {
|
||||
defer app.ReleaseCtx(c)
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
c.index = -1
|
||||
c.indexRoute = -1
|
||||
res = app.next(c)
|
||||
}
|
||||
utils.AssertEqual(b, true, res)
|
||||
utils.AssertEqual(b, 31, c.index)
|
||||
utils.AssertEqual(b, 31, c.indexRoute)
|
||||
}
|
||||
|
||||
// go test -v ./... -run=^$ -bench=Benchmark_Route_Match -benchmem -count=4
|
||||
|
Loading…
x
Reference in New Issue
Block a user