diff --git a/echo.go b/echo.go index ab17b201..8e5e9a42 100644 --- a/echo.go +++ b/echo.go @@ -86,9 +86,9 @@ type ( // Route contains a handler and information for matching against requests. Route struct { - Method string `json:"method"` - Path string `json:"path"` - Handler string `json:"handler"` + Method string `json:"method"` + Path string `json:"path"` + Name string `json:"name"` } // HTTPError represents an error that occurred while handling a request. @@ -121,7 +121,7 @@ type ( // i is the interface for Echo and Group. i interface { - GET(string, HandlerFunc, ...MiddlewareFunc) + GET(string, HandlerFunc, ...MiddlewareFunc) *Route } ) @@ -355,84 +355,88 @@ func (e *Echo) Use(middleware ...MiddlewareFunc) { // CONNECT registers a new CONNECT route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(CONNECT, path, h, m...) +func (e *Echo) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(CONNECT, path, h, m...) } // DELETE registers a new DELETE route for a path with matching handler in the router // with optional route-level middleware. -func (e *Echo) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(DELETE, path, h, m...) +func (e *Echo) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(DELETE, path, h, m...) } // GET registers a new GET route for a path with matching handler in the router // with optional route-level middleware. -func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(GET, path, h, m...) +func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(GET, path, h, m...) } // HEAD registers a new HEAD route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(HEAD, path, h, m...) +func (e *Echo) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(HEAD, path, h, m...) } // OPTIONS registers a new OPTIONS route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(OPTIONS, path, h, m...) +func (e *Echo) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(OPTIONS, path, h, m...) } // PATCH registers a new PATCH route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(PATCH, path, h, m...) +func (e *Echo) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(PATCH, path, h, m...) } // POST registers a new POST route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) POST(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(POST, path, h, m...) +func (e *Echo) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(POST, path, h, m...) } // PUT registers a new PUT route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(PUT, path, h, m...) +func (e *Echo) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(PUT, path, h, m...) } // TRACE registers a new TRACE route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(TRACE, path, h, m...) +func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.add(TRACE, path, h, m...) } // Any registers a new route for all HTTP methods and path with matching handler // in the router with optional route-level middleware. -func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) { +func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route { + routes := make([]*Route, 0) for _, m := range methods { - e.add(m, path, handler, middleware...) + routes = append(routes, e.add(m, path, handler, middleware...)) } + return routes } // Match registers a new route for multiple HTTP methods and path with matching // handler in the router with optional route-level middleware. -func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { +func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route { + routes := make([]*Route, 0) for _, m := range methods { - e.add(m, path, handler, middleware...) + routes = append(routes, e.add(m, path, handler, middleware...)) } + return routes } // Static registers a new route with path prefix to serve static files from the // provided root directory. -func (e *Echo) Static(prefix, root string) { +func (e *Echo) Static(prefix, root string) *Route { if root == "" { root = "." // For security we want to restrict to CWD. } - static(e, prefix, root) + return static(e, prefix, root) } -func static(i i, prefix, root string) { +func static(i i, prefix, root string) *Route { h := func(c Context) error { p, err := PathUnescape(c.Param("*")) if err != nil { @@ -443,20 +447,20 @@ func static(i i, prefix, root string) { } i.GET(prefix, h) if prefix == "/" { - i.GET(prefix+"*", h) - } else { - i.GET(prefix+"/*", h) + return i.GET(prefix+"*", h) } + + return i.GET(prefix+"/*", h) } // File registers a new route with path to serve a static file. -func (e *Echo) File(path, file string) { - e.GET(path, func(c Context) error { +func (e *Echo) File(path, file string) *Route { + return e.GET(path, func(c Context) error { return c.File(file) }) } -func (e *Echo) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { +func (e *Echo) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { name := handlerName(handler) e.router.Add(method, path, func(c Context) error { h := handler @@ -467,11 +471,12 @@ func (e *Echo) add(method, path string, handler HandlerFunc, middleware ...Middl return h(c) }) r := &Route{ - Method: method, - Path: path, - Handler: name, + Method: method, + Path: path, + Name: name, } e.router.routes[method+path] = r + return r } // Group creates a new router group with prefix and optional group-level middleware. @@ -483,12 +488,22 @@ func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) { // URI generates a URI from handler. func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string { + name := handlerName(handler) + return e.Reverse(name, params...) +} + +// URL is an alias for `URI` function. +func (e *Echo) URL(h HandlerFunc, params ...interface{}) string { + return e.URI(h, params...) +} + +// Reverse generates an URL from route name and provided parameters +func (e *Echo) Reverse(name string, params ...interface{}) string { uri := new(bytes.Buffer) ln := len(params) n := 0 - name := handlerName(handler) for _, r := range e.router.routes { - if r.Handler == name { + if r.Name == name { for i, l := 0, len(r.Path); i < l; i++ { if r.Path[i] == ':' && n < ln { for ; i < l && r.Path[i] != '/'; i++ { @@ -506,11 +521,6 @@ func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string { return uri.String() } -// URL is an alias for `URI` function. -func (e *Echo) URL(h HandlerFunc, params ...interface{}) string { - return e.URI(h, params...) -} - // Routes returns the registered routes. func (e *Echo) Routes() []*Route { routes := []*Route{} diff --git a/group.go b/group.go index 799a8f90..b4ed2339 100644 --- a/group.go +++ b/group.go @@ -26,48 +26,48 @@ func (g *Group) Use(middleware ...MiddlewareFunc) { } // CONNECT implements `Echo#CONNECT()` for sub-routes within the Group. -func (g *Group) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(CONNECT, path, h, m...) +func (g *Group) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(CONNECT, path, h, m...) } // DELETE implements `Echo#DELETE()` for sub-routes within the Group. -func (g *Group) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(DELETE, path, h, m...) +func (g *Group) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(DELETE, path, h, m...) } // GET implements `Echo#GET()` for sub-routes within the Group. -func (g *Group) GET(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(GET, path, h, m...) +func (g *Group) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(GET, path, h, m...) } // HEAD implements `Echo#HEAD()` for sub-routes within the Group. -func (g *Group) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(HEAD, path, h, m...) +func (g *Group) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(HEAD, path, h, m...) } // OPTIONS implements `Echo#OPTIONS()` for sub-routes within the Group. -func (g *Group) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(OPTIONS, path, h, m...) +func (g *Group) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(OPTIONS, path, h, m...) } // PATCH implements `Echo#PATCH()` for sub-routes within the Group. -func (g *Group) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(PATCH, path, h, m...) +func (g *Group) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(PATCH, path, h, m...) } // POST implements `Echo#POST()` for sub-routes within the Group. -func (g *Group) POST(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(POST, path, h, m...) +func (g *Group) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(POST, path, h, m...) } // PUT implements `Echo#PUT()` for sub-routes within the Group. -func (g *Group) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(PUT, path, h, m...) +func (g *Group) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(PUT, path, h, m...) } // TRACE implements `Echo#TRACE()` for sub-routes within the Group. -func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(TRACE, path, h, m...) +func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.add(TRACE, path, h, m...) } // Any implements `Echo#Any()` for sub-routes within the Group. @@ -102,12 +102,12 @@ func (g *Group) File(path, file string) { g.echo.File(g.prefix+path, file) } -func (g *Group) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { +func (g *Group) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { // Combine into a new slice to avoid accidentally passing the same slice for // multiple routes, which would lead to later add() calls overwriting the // middleware from earlier calls. m := []MiddlewareFunc{} m = append(m, g.middleware...) m = append(m, middleware...) - g.echo.add(method, g.prefix+path, handler, m...) + return g.echo.add(method, g.prefix+path, handler, m...) }