mirror of
https://github.com/gofiber/fiber.git
synced 2025-02-21 19:53:19 +00:00
🚀 improve routing behavior
This commit is contained in:
parent
cff454dfc2
commit
67caca823b
@ -916,6 +916,7 @@ func Test_Ctx_Params(t *testing.T) {
|
|||||||
app.Get("/test3/*/blafasel/*", func(c *Ctx) {
|
app.Get("/test3/*/blafasel/*", func(c *Ctx) {
|
||||||
utils.AssertEqual(t, "1111", c.Params("*1"))
|
utils.AssertEqual(t, "1111", c.Params("*1"))
|
||||||
utils.AssertEqual(t, "2222", c.Params("*2"))
|
utils.AssertEqual(t, "2222", c.Params("*2"))
|
||||||
|
utils.AssertEqual(t, "1111", c.Params("*"))
|
||||||
})
|
})
|
||||||
app.Get("/test4/:optional?", func(c *Ctx) {
|
app.Get("/test4/:optional?", func(c *Ctx) {
|
||||||
utils.AssertEqual(t, "", c.Params("optional"))
|
utils.AssertEqual(t, "", c.Params("optional"))
|
||||||
|
31
path.go
31
path.go
@ -30,7 +30,6 @@ type routeSegment struct {
|
|||||||
ParamName string
|
ParamName string
|
||||||
ComparePart string // search part to find the end of the parameter
|
ComparePart string // search part to find the end of the parameter
|
||||||
PartCount int // how often is the search part contained in the non-param segments? -> necessary for greedy search
|
PartCount int // how often is the search part contained in the non-param segments? -> necessary for greedy search
|
||||||
IsWildcard bool
|
|
||||||
IsGreedy bool
|
IsGreedy bool
|
||||||
IsOptional bool
|
IsOptional bool
|
||||||
IsLast bool
|
IsLast bool
|
||||||
@ -48,7 +47,6 @@ const (
|
|||||||
var (
|
var (
|
||||||
// list of possible parameter and segment delimiter
|
// list of possible parameter and segment delimiter
|
||||||
// slash has a special role, unlike the other parameters it must not be interpreted as a parameter
|
// slash has a special role, unlike the other parameters it must not be interpreted as a parameter
|
||||||
// TODO '(' ')' delimiters for regex patterns
|
|
||||||
routeDelimiter = []byte{slashDelimiter, '-', '.'}
|
routeDelimiter = []byte{slashDelimiter, '-', '.'}
|
||||||
// list of chars for the parameter recognising
|
// list of chars for the parameter recognising
|
||||||
parameterStartChars = []byte{wildcardParam, plusParam, paramStarterChar}
|
parameterStartChars = []byte{wildcardParam, plusParam, paramStarterChar}
|
||||||
@ -217,9 +215,8 @@ func (routeParser *routeParser) getMatch(s string, partialCheck bool) ([][2]int,
|
|||||||
var i, paramsIterator, partLen, paramStart int
|
var i, paramsIterator, partLen, paramStart int
|
||||||
for index, segment := range routeParser.segs {
|
for index, segment := range routeParser.segs {
|
||||||
partLen = len(s)
|
partLen = len(s)
|
||||||
// check parameter
|
// check const segment
|
||||||
if !segment.IsParam {
|
if !segment.IsParam {
|
||||||
// check const segment
|
|
||||||
optionalPart := false
|
optionalPart := false
|
||||||
i = len(segment.Const)
|
i = len(segment.Const)
|
||||||
// check if the end of the segment is a optional slash and then if the segement is optional or the last one
|
// check if the end of the segment is a optional slash and then if the segement is optional or the last one
|
||||||
@ -284,29 +281,21 @@ func findParamLen(s string, segments []routeSegment, currIndex int) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compareSeg := segments[currIndex+1]
|
compareSeg := segments[currIndex+1]
|
||||||
// check if parameter segments are directly after each other
|
// check if parameter segments are directly after each other and if one of them is greedy
|
||||||
if compareSeg.IsParam {
|
if compareSeg.IsParam && !segments[currIndex].IsGreedy && !compareSeg.IsGreedy && len(s) > 0 {
|
||||||
// and if one of them is greedy
|
// in case the next parameter or the current parameter is not a wildcard its not greedy, we only want one character
|
||||||
if !segments[currIndex].IsGreedy && !compareSeg.IsGreedy && len(s) > 0 {
|
return 1
|
||||||
// in case the next parameter or the current parameter is not a wildcard its not greedy, we only want one character
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Search the parameters until the next constant part
|
||||||
return findParamLenUntilNextConstSeg(s, segments[currIndex])
|
|
||||||
}
|
|
||||||
|
|
||||||
// findParamLenUntilNextConstSeg Search the parameters until the next constant part
|
|
||||||
func findParamLenUntilNextConstSeg(s string, segment routeSegment) int {
|
|
||||||
// special logic for greedy params
|
// special logic for greedy params
|
||||||
if segment.IsGreedy {
|
if segments[currIndex].IsGreedy {
|
||||||
searchCount := strings.Count(s, segment.ComparePart)
|
searchCount := strings.Count(s, segments[currIndex].ComparePart)
|
||||||
if searchCount > 1 {
|
if searchCount > 1 {
|
||||||
return findGreedyParamLen(s, searchCount, segment)
|
return findGreedyParamLen(s, searchCount, segments[currIndex])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constPosition := strings.Index(s, segment.ComparePart); constPosition != -1 {
|
if constPosition := strings.Index(s, segments[currIndex].ComparePart); constPosition != -1 {
|
||||||
return constPosition
|
return constPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
87
path_test.go
87
path_test.go
@ -12,6 +12,93 @@ import (
|
|||||||
utils "github.com/gofiber/utils"
|
utils "github.com/gofiber/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// go test -race -run Test_Path_parseRoute
|
||||||
|
func Test_Path_parseRoute(t *testing.T) {
|
||||||
|
var rp routeParser
|
||||||
|
|
||||||
|
rp = parseRoute("/shop/product/::filter/color::color/size::size")
|
||||||
|
utils.AssertEqual(t, routeParser{
|
||||||
|
segs: []routeSegment{
|
||||||
|
{Const: "/shop/product/:"},
|
||||||
|
{IsParam: true, ParamName: "filter", ComparePart: "/color:", PartCount: 1},
|
||||||
|
{Const: "/color:"},
|
||||||
|
{IsParam: true, ParamName: "color", ComparePart: "/size:", PartCount: 1},
|
||||||
|
{Const: "/size:"},
|
||||||
|
{IsParam: true, ParamName: "size", IsLast: true},
|
||||||
|
},
|
||||||
|
params: []string{"filter", "color", "size"},
|
||||||
|
wildCardCount: 0,
|
||||||
|
plusCount: 0,
|
||||||
|
}, rp)
|
||||||
|
|
||||||
|
rp = parseRoute("/api/v1/:param/abc/*")
|
||||||
|
utils.AssertEqual(t, routeParser{
|
||||||
|
segs: []routeSegment{
|
||||||
|
{Const: "/api/v1/"},
|
||||||
|
{IsParam: true, ParamName: "param", ComparePart: "/abc", PartCount: 1},
|
||||||
|
{Const: "/abc/"},
|
||||||
|
{IsParam: true, ParamName: "*1", IsGreedy: true, IsOptional: true, IsLast: true},
|
||||||
|
},
|
||||||
|
params: []string{"param", "*1"},
|
||||||
|
wildCardCount: 1,
|
||||||
|
plusCount: 0,
|
||||||
|
}, rp)
|
||||||
|
|
||||||
|
rp = parseRoute("/api/*/:param/:param2")
|
||||||
|
utils.AssertEqual(t, routeParser{
|
||||||
|
segs: []routeSegment{
|
||||||
|
{Const: "/api/"},
|
||||||
|
{IsParam: true, ParamName: "*1", IsGreedy: true, IsOptional: true, ComparePart: "/", PartCount: 2},
|
||||||
|
{Const: "/"},
|
||||||
|
{IsParam: true, ParamName: "param", ComparePart: "/", PartCount: 1},
|
||||||
|
{Const: "/"},
|
||||||
|
{IsParam: true, ParamName: "param2", IsLast: true},
|
||||||
|
},
|
||||||
|
params: []string{"*1", "param", "param2"},
|
||||||
|
wildCardCount: 1,
|
||||||
|
plusCount: 0,
|
||||||
|
}, rp)
|
||||||
|
|
||||||
|
rp = parseRoute("/test:optional?:optional2?")
|
||||||
|
utils.AssertEqual(t, routeParser{
|
||||||
|
segs: []routeSegment{
|
||||||
|
{Const: "/test"},
|
||||||
|
{IsParam: true, ParamName: "optional", IsOptional: true},
|
||||||
|
{IsParam: true, ParamName: "optional2", IsOptional: true, IsLast: true},
|
||||||
|
},
|
||||||
|
params: []string{"optional", "optional2"},
|
||||||
|
wildCardCount: 0,
|
||||||
|
plusCount: 0,
|
||||||
|
}, rp)
|
||||||
|
|
||||||
|
rp = parseRoute("/config/+.json")
|
||||||
|
utils.AssertEqual(t, routeParser{
|
||||||
|
segs: []routeSegment{
|
||||||
|
{Const: "/config/"},
|
||||||
|
{IsParam: true, ParamName: "+1", IsGreedy: true, IsOptional: false, ComparePart: ".json", PartCount: 0},
|
||||||
|
{Const: ".json", IsLast: true},
|
||||||
|
},
|
||||||
|
params: []string{"+1"},
|
||||||
|
wildCardCount: 0,
|
||||||
|
plusCount: 1,
|
||||||
|
}, rp)
|
||||||
|
|
||||||
|
rp = parseRoute("/api/:day.:month?.:year?")
|
||||||
|
utils.AssertEqual(t, routeParser{
|
||||||
|
segs: []routeSegment{
|
||||||
|
{Const: "/api/"},
|
||||||
|
{IsParam: true, ParamName: "day", IsOptional: false, ComparePart: ".", PartCount: 2},
|
||||||
|
{Const: "."},
|
||||||
|
{IsParam: true, ParamName: "month", IsOptional: true, ComparePart: ".", PartCount: 1},
|
||||||
|
{Const: "."},
|
||||||
|
{IsParam: true, ParamName: "year", IsOptional: true, IsLast: true},
|
||||||
|
},
|
||||||
|
params: []string{"day", "month", "year"},
|
||||||
|
wildCardCount: 0,
|
||||||
|
plusCount: 0,
|
||||||
|
}, rp)
|
||||||
|
}
|
||||||
|
|
||||||
// go test -race -run Test_Path_matchParams
|
// go test -race -run Test_Path_matchParams
|
||||||
func Test_Path_matchParams(t *testing.T) {
|
func Test_Path_matchParams(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user