From 6f0a227a5a9f9d9bd49106053cdd0c03c6eb170b Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Sun, 28 Apr 2019 22:22:35 -0700 Subject: [PATCH] Built-in capability to run multiple hosts Signed-off-by: Vishal Rana --- echo.go | 36 ++++++++++++++++++++++++++++++------ group.go | 3 ++- router.go | 5 ++--- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/echo.go b/echo.go index 032bd002..84b70e73 100644 --- a/echo.go +++ b/echo.go @@ -70,6 +70,7 @@ type ( middleware []MiddlewareFunc maxParam *int router *Router + routers map[string]*Router notFoundHandler HandlerFunc pool sync.Pool Server *http.Server @@ -308,6 +309,7 @@ func New() (e *Echo) { return e.NewContext(nil, nil) } e.router = NewRouter(e) + e.routers = map[string]*Router{} return } @@ -481,11 +483,10 @@ func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route { }, m...) } -// Add registers a new route for an HTTP method and path with matching handler -// in the router with optional route-level middleware. -func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { +func (e *Echo) add(host, method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { name := handlerName(handler) - e.router.Add(method, path, func(c Context) error { + router := e.findRouter(host) + router.Add(method, path, func(c Context) error { h := handler // Chain middleware for i := len(middleware) - 1; i >= 0; i-- { @@ -502,6 +503,20 @@ func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...Middl return r } +// Add registers a new route for an HTTP method and path with matching handler +// in the router with optional route-level middleware. +func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { + return e.add("", method, path, handler, middleware...) +} + +// Host creates a new router group for the provided host and optional host-level middleware. +func (e *Echo) Host(name string, m ...MiddlewareFunc) (g *Group) { + e.routers[name] = NewRouter(e) + g = &Group{host: name, echo: e} + g.Use(m...) + return +} + // Group creates a new router group with prefix and optional group-level middleware. func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) { g = &Group{prefix: prefix, echo: e} @@ -574,12 +589,12 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) { h := NotFoundHandler if e.premiddleware == nil { - e.router.Find(r.Method, getPath(r), c) + e.findRouter(r.Host).Find(r.Method, getPath(r), c) h = c.Handler() h = applyMiddleware(h, e.middleware...) } else { h = func(c Context) error { - e.router.Find(r.Method, getPath(r), c) + e.findRouter(r.Host).Find(r.Method, getPath(r), c) h := c.Handler() h = applyMiddleware(h, e.middleware...) return h(c) @@ -761,6 +776,15 @@ func getPath(r *http.Request) string { return path } +func (e *Echo) findRouter(host string) *Router { + if len(e.routers) > 0 { + if r, ok := e.routers[host]; ok { + return r + } + } + return e.router +} + func handlerName(h HandlerFunc) string { t := reflect.ValueOf(h).Type() if t.Kind() == reflect.Func { diff --git a/group.go b/group.go index 3e3732b6..50b308a2 100644 --- a/group.go +++ b/group.go @@ -10,6 +10,7 @@ type ( // routes that share a common middleware or functionality that should be separate // from the parent echo instance while still inheriting from it. Group struct { + host string prefix string middleware []MiddlewareFunc echo *Echo @@ -117,5 +118,5 @@ func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...Midd m := make([]MiddlewareFunc, 0, len(g.middleware)+len(middleware)) m = append(m, g.middleware...) m = append(m, middleware...) - return g.echo.Add(method, g.prefix+path, handler, m...) + return g.echo.add(g.host, method, g.prefix+path, handler, m...) } diff --git a/router.go b/router.go index 73f0b68b..05b85356 100644 --- a/router.go +++ b/router.go @@ -79,14 +79,13 @@ func (r *Router) Add(method, path string, h HandlerFunc) { if i == l { r.insert(method, path[:i], h, pkind, ppath, pnames) - return + } else { + r.insert(method, path[:i], nil, pkind, "", nil) } - r.insert(method, path[:i], nil, pkind, "", nil) } else if path[i] == '*' { r.insert(method, path[:i], nil, skind, "", nil) pnames = append(pnames, "*") r.insert(method, path[:i+1], h, akind, ppath, pnames) - return } }