mirror of
https://github.com/gin-gonic/gin.git
synced 2026-06-10 14:44:37 +08:00
Merge 8f39ea663a8ef23001ee7b30e8d66f63367bc1a7 into d7776de7d444935ea4385999711bd6331a98fecb
This commit is contained in:
commit
1e17cf86f0
9
gin.go
9
gin.go
@ -96,6 +96,10 @@ type Engine struct {
|
||||
// (used for routing HTTP requests) happens only once, even if called multiple times concurrently.
|
||||
routeTreesUpdated sync.Once
|
||||
|
||||
|
||||
// mu protects concurrent access to trees
|
||||
mu sync.RWMutex
|
||||
|
||||
// RedirectTrailingSlash enables automatic redirection if the current route can't be matched but a
|
||||
// handler for the path with (without) the trailing slash exists.
|
||||
// For example if /foo/ is requested but a route only exists for /foo, the
|
||||
@ -368,6 +372,9 @@ func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
|
||||
|
||||
debugPrintRoute(method, path, handlers)
|
||||
|
||||
engine.mu.Lock()
|
||||
defer engine.mu.Unlock()
|
||||
|
||||
root := engine.trees.get(method)
|
||||
if root == nil {
|
||||
root = new(node)
|
||||
@ -388,6 +395,8 @@ func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
|
||||
// Routes returns a slice of registered routes, including some useful information, such as:
|
||||
// the http method, path, and the handler name.
|
||||
func (engine *Engine) Routes() (routes RoutesInfo) {
|
||||
engine.mu.RLock()
|
||||
defer engine.mu.RUnlock()
|
||||
for _, tree := range engine.trees {
|
||||
routes = iterate("", tree.method, routes, tree.root)
|
||||
}
|
||||
|
||||
32
gin_test.go
32
gin_test.go
@ -1067,6 +1067,38 @@ func TestLiteralColonWithHTTPServer(t *testing.T) {
|
||||
assert.Contains(t, w2.Body.String(), "foo")
|
||||
}
|
||||
|
||||
func TestConcurrentAddRouteAndRoutes(t *testing.T) {
|
||||
router := New()
|
||||
|
||||
done := make(chan bool)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(n int) {
|
||||
router.GET(fmt.Sprintf("/route%d", n), func(c *Context) {
|
||||
c.String(http.StatusOK, fmt.Sprintf("route%d", n))
|
||||
})
|
||||
router.POST(fmt.Sprintf("/route%d", n), func(c *Context) {
|
||||
c.String(http.StatusOK, fmt.Sprintf("route%d", n))
|
||||
})
|
||||
done <- true
|
||||
}(i)
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
_ = router.Routes()
|
||||
done <- true
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
routes := router.Routes()
|
||||
assert.Len(t, routes, 20)
|
||||
}
|
||||
|
||||
// Test that updateRouteTrees is called only once
|
||||
func TestUpdateRouteTreesCalledOnce(t *testing.T) {
|
||||
SetMode(TestMode)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user