Skip to content

Commit 45402bb

Browse files
committed
Add echo.OnAddRouteHandler field. As name says - this handler is called when new route is registered.
1 parent f1cf1ec commit 45402bb

File tree

2 files changed

+66
-11
lines changed

2 files changed

+66
-11
lines changed

echo.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,28 @@ import (
6161

6262
type (
6363
// Echo is the top-level framework instance.
64+
//
65+
// Goroutine safety: Do not mutate Echo instance fields after server has started. Accessing these
66+
// fields from handlers/middlewares and changing field values at the same time leads to data-races.
67+
// Same rule applies to adding new routes after server has been started - Adding a route is not Goroutine safe action.
6468
Echo struct {
6569
filesystem
6670
common
6771
// startupMutex is mutex to lock Echo instance access during server configuration and startup. Useful for to get
6872
// listener address info (on which interface/port was listener binded) without having data races.
69-
startupMutex sync.RWMutex
73+
startupMutex sync.RWMutex
74+
colorer *color.Color
75+
76+
// premiddleware are middlewares that are run before routing is done. In case pre-middleware returns an error router
77+
// will not be called at all and execution ends up in global error handler.
78+
premiddleware []MiddlewareFunc
79+
middleware []MiddlewareFunc
80+
maxParam *int
81+
router *Router
82+
routers map[string]*Router
83+
pool sync.Pool
84+
7085
StdLogger *stdLog.Logger
71-
colorer *color.Color
72-
premiddleware []MiddlewareFunc
73-
middleware []MiddlewareFunc
74-
maxParam *int
75-
router *Router
76-
routers map[string]*Router
77-
pool sync.Pool
7886
Server *http.Server
7987
TLSServer *http.Server
8088
Listener net.Listener
@@ -92,6 +100,9 @@ type (
92100
Logger Logger
93101
IPExtractor IPExtractor
94102
ListenerNetwork string
103+
104+
// OnAddRouteHandler is called when Echo adds new route to specific host router.
105+
OnAddRouteHandler func(host string, route Route, handler HandlerFunc, middleware []MiddlewareFunc)
95106
}
96107

97108
// Route contains a handler and information for matching against requests.
@@ -526,14 +537,20 @@ func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route {
526537
return e.file(path, file, e.GET, m...)
527538
}
528539

529-
func (e *Echo) add(host, method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
540+
func (e *Echo) add(host, method, path string, handler HandlerFunc, middlewares ...MiddlewareFunc) *Route {
530541
router := e.findRouter(host)
531542
//FIXME: when handler+middleware are both nil ... make it behave like handler removal
532543
name := handlerName(handler)
533-
return router.add(method, path, name, func(c Context) error {
534-
h := applyMiddleware(handler, middleware...)
544+
route := router.add(method, path, name, func(c Context) error {
545+
h := applyMiddleware(handler, middlewares...)
535546
return h(c)
536547
})
548+
549+
if e.OnAddRouteHandler != nil {
550+
e.OnAddRouteHandler(host, *route, handler, middlewares)
551+
}
552+
553+
return route
537554
}
538555

539556
// Add registers a new route for an HTTP method and path with matching handler

echo_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,44 @@ func TestEchoListenerNetworkInvalid(t *testing.T) {
14781478
assert.Equal(t, ErrInvalidListenerNetwork, e.Start(":1323"))
14791479
}
14801480

1481+
func TestEcho_OnAddRouteHandler(t *testing.T) {
1482+
type rr struct {
1483+
host string
1484+
route Route
1485+
handler HandlerFunc
1486+
middleware []MiddlewareFunc
1487+
}
1488+
dummyHandler := func(Context) error { return nil }
1489+
e := New()
1490+
1491+
added := make([]rr, 0)
1492+
e.OnAddRouteHandler = func(host string, route Route, handler HandlerFunc, middleware []MiddlewareFunc) {
1493+
added = append(added, rr{
1494+
host: host,
1495+
route: route,
1496+
handler: handler,
1497+
middleware: middleware,
1498+
})
1499+
}
1500+
1501+
e.GET("/static", NotFoundHandler)
1502+
e.Host("domain.site").GET("/static/*", dummyHandler, func(next HandlerFunc) HandlerFunc {
1503+
return func(c Context) error {
1504+
return next(c)
1505+
}
1506+
})
1507+
1508+
assert.Len(t, added, 2)
1509+
1510+
assert.Equal(t, "", added[0].host)
1511+
assert.Equal(t, Route{Method: http.MethodGet, Path: "/static", Name: "github.com/labstack/echo/v4.glob..func1"}, added[0].route)
1512+
assert.Len(t, added[0].middleware, 0)
1513+
1514+
assert.Equal(t, "domain.site", added[1].host)
1515+
assert.Equal(t, Route{Method: http.MethodGet, Path: "/static/*", Name: "github.com/labstack/echo/v4.TestEcho_OnAddRouteHandler.func1"}, added[1].route)
1516+
assert.Len(t, added[1].middleware, 1)
1517+
}
1518+
14811519
func TestEchoReverse(t *testing.T) {
14821520
e := New()
14831521
dummyHandler := func(Context) error { return nil }

0 commit comments

Comments
 (0)