introduction
Note: There are errors in the original text of this article, and the original text is not changed, but an errata was performed at the end. Please note that you will read the end of the article.
Gin related version v1.9.1
The bug will occur when you register two routes as follows.
r := () ("/static/", func(c *) { (200, "static") }) ("/static/*file", func(c *) { (200, "static file") }) ()
The above code will report an error:
panic: runtime error: index out of range [0] with length 0
analyze
Although Gin itself will actively generate many panics when building a routing tree, the above panic is obviously an accident.
This bug is caused by the specificity of the catchAll wildcard.
catchAll wildcards are written*paramname
, but when it builds the routing tree, it will match one forward/
。
Because catchAll wildcards usually exist to match paths, the classic application of catchAll wildcards in gin is to configure static file servers.
Refer to the gin projectdocument:
func (group *RouterGroup) StaticFS(relativePath string, fs ) IRoutes { if (relativePath, ":") || (relativePath, "*") { panic("URL parameters can not be used when serving a static folder") } handler := (relativePath, fs) urlPattern := (relativePath, "/*filepath") // Register GET and HEAD handlers (urlPattern, handler) (urlPattern, handler) return () }
Once you useStatic
The related functions configure the static file service and will eventually call the above method.
It uses the one you passed inrelativePath
and/*filepath
Combined into the final url:relativePath/*filepath
。
If the path you passed in is/static
, the final url is/static/*filepath
。
This route will match all/static/
The url at the beginning and assign all the following content tofilepath
。
Yes, it's all, including the ones behind/
,for examplehtml/group1/
, that is, it can be passedfilepath
Access to the subdirectory.
But there is actually a mistake in what is described above, you thinkfilepath
The saved content ishtml/group1/
。
Actually it is/html/group1/
。
catchAll wildcard will try to match one more forward/
If you don't have this in your route/
, an error will be reported.
The special feature of this feature leads to a bug in gin, which is when you have registered/static/
After routing, register/static/*file
When we're in/static/
Insert on node*filepath
Instead/*filepath
, This causes the program to match one forward after determining that this is a catchAll route./
, at this timei--
After that, it becomes a negative number, which leads toindex out of range
Error.
You may think that the error is correct, so you need to pay attention to distinguishing the panic caused by the error and the bug.
i-- if path[i] != '/' { panic("no / before catch-all in path '" + fullPath + "'") }
What I said is the errorpanic("no / before catch-all in path '" + fullPath + "'")
。
The bug-generated panic is generated ini--
Query after it becomes negativeif path[i] != '/'
hour.
If it is simple to deal with, it should be correct herei
judging the value of , then actively panic to throw an error that can make people understand.
Of course, in order to solve this problem itself, the above code can be modified to:
r := () ("/static", func(c *) { (200, "static") }) ("/static/*file", func(c *) { (200, "static file") }) ()
Do not add the end of the first route/
, you can avoid this bug.
Errata
As mentioned earlierpanic: runtime error: index out of range [0] with length 0
An error was reported, but it was obviously not an error with index negative, it was my previous predictioni--
Wishful thinking when it is negative.
Actually this error occurred ini--
The above lines:
if len() > 0 && [len()-1] == '/' { pathSeg := ([0].path, "/", 2)[0] panic("catch-all wildcard '" + path + "' in new path '" + fullPath + "' conflicts with existing path segment '" + pathSeg + "' in existing prefix '" + + pathSeg + "'") } // currently fixed width 1 for '/' i-- if path[i] != '/' { panic("no / before catch-all in path '" + fullPath + "'") }
This line:pathSeg := ([0].path, "/", 2)[0]
。
Herechildren
The length is actually 0, but here it is defaultchildren
There is content.
See the content of the error reported by panic:catch-all wildcard "path" in new path "fullPath" conflicts with existing path segment "pathSeg" in existing prefix "" + "pathSeg"
。
The catchAll wildcard character conflicts with the current path, but here Gin defaults to this timeI still haven't figured out the logic of not being empty.
The above is the detailed content of the Go Gin framework routing-related bug analysis. For more information about Go Gin framework routing bugs, please follow my other related articles!