mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
add HandleMany to controller's Before/AfterActivation feature as requested at: https://github.com/kataras/iris/issues/1292
Former-commit-id: c021f49522a214ddc3978a1c8f5e8d32f029eb2d
This commit is contained in:
parent
33dfb42d73
commit
f8d19b3ed2
|
@ -36,6 +36,7 @@ func basicMVC(app *mvc.Application) {
|
||||||
|
|
||||||
// GET: http://localhost:8080/basic
|
// GET: http://localhost:8080/basic
|
||||||
// GET: http://localhost:8080/basic/custom
|
// GET: http://localhost:8080/basic/custom
|
||||||
|
// GET: http://localhost:8080/basic/custom2
|
||||||
app.Handle(new(basicController))
|
app.Handle(new(basicController))
|
||||||
|
|
||||||
// All dependencies of the parent *mvc.Application
|
// All dependencies of the parent *mvc.Application
|
||||||
|
@ -73,7 +74,7 @@ type basicController struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *basicController) BeforeActivation(b mvc.BeforeActivation) {
|
func (c *basicController) BeforeActivation(b mvc.BeforeActivation) {
|
||||||
b.Handle("GET", "/custom", "Custom")
|
b.HandleMany("GET", "/custom /custom2", "Custom")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *basicController) AfterActivation(a mvc.AfterActivation) {
|
func (c *basicController) AfterActivation(a mvc.AfterActivation) {
|
||||||
|
|
|
@ -26,7 +26,9 @@ type shared interface {
|
||||||
Name() string
|
Name() string
|
||||||
Router() router.Party
|
Router() router.Party
|
||||||
GetRoute(methodName string) *router.Route
|
GetRoute(methodName string) *router.Route
|
||||||
|
GetRoutes(methodName string) []*router.Route
|
||||||
Handle(httpMethod, path, funcName string, middleware ...context.Handler) *router.Route
|
Handle(httpMethod, path, funcName string, middleware ...context.Handler) *router.Route
|
||||||
|
HandleMany(httpMethod, path, funcName string, middleware ...context.Handler) []*router.Route
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeforeActivation is being used as the only one input argument of a
|
// BeforeActivation is being used as the only one input argument of a
|
||||||
|
@ -77,8 +79,8 @@ type ControllerActivator struct {
|
||||||
|
|
||||||
// the already-registered routes, key = the controller's function name.
|
// the already-registered routes, key = the controller's function name.
|
||||||
// End-devs can change some properties of the *Route on the `BeforeActivator` by using the
|
// End-devs can change some properties of the *Route on the `BeforeActivator` by using the
|
||||||
// `GetRoute(functionName)`. It's a shield against duplications as well.
|
// `GetRoute/GetRoutes(functionName)`.
|
||||||
routes map[string]*router.Route
|
routes map[string][]*router.Route
|
||||||
|
|
||||||
// the bindings that comes from the Engine and the controller's filled fields if any.
|
// the bindings that comes from the Engine and the controller's filled fields if any.
|
||||||
// Can be bind-ed to the the new controller's fields and method that is fired
|
// Can be bind-ed to the the new controller's fields and method that is fired
|
||||||
|
@ -132,7 +134,7 @@ func newControllerActivator(router router.Party, controller interface{}, depende
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func whatReservedMethods(typ reflect.Type) map[string]*router.Route {
|
func whatReservedMethods(typ reflect.Type) map[string][]*router.Route {
|
||||||
methods := []string{"BeforeActivation", "AfterActivation"}
|
methods := []string{"BeforeActivation", "AfterActivation"}
|
||||||
// BeforeActivatior/AfterActivation are not routes but they are
|
// BeforeActivatior/AfterActivation are not routes but they are
|
||||||
// reserved names*
|
// reserved names*
|
||||||
|
@ -140,9 +142,9 @@ func whatReservedMethods(typ reflect.Type) map[string]*router.Route {
|
||||||
methods = append(methods, "BeginRequest", "EndRequest")
|
methods = append(methods, "BeginRequest", "EndRequest")
|
||||||
}
|
}
|
||||||
|
|
||||||
routes := make(map[string]*router.Route, len(methods))
|
routes := make(map[string][]*router.Route, len(methods))
|
||||||
for _, m := range methods {
|
for _, m := range methods {
|
||||||
routes[m] = &router.Route{}
|
routes[m] = []*router.Route{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return routes
|
return routes
|
||||||
|
@ -199,7 +201,25 @@ func (c *ControllerActivator) Router() router.Party {
|
||||||
return c.router
|
return c.router
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRoute returns a registered route based on the controller's method name.
|
// GetRoute returns the first registered route based on the controller's method name.
|
||||||
|
// It can be used to change the route's name, which is useful for reverse routing
|
||||||
|
// inside views. Custom routes can be registered with `Handle`, which returns the *Route.
|
||||||
|
// This method exists mostly for the automatic method parsing based on the known patterns
|
||||||
|
// inside a controller.
|
||||||
|
//
|
||||||
|
// A check for `nil` is necessary for unregistered methods.
|
||||||
|
//
|
||||||
|
// See `GetRoutes` and `Handle` too.
|
||||||
|
func (c *ControllerActivator) GetRoute(methodName string) *router.Route {
|
||||||
|
routes := c.GetRoutes(methodName)
|
||||||
|
if len(routes) > 0 {
|
||||||
|
return routes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoutes returns one or more registered route based on the controller's method name.
|
||||||
// It can be used to change the route's name, which is useful for reverse routing
|
// It can be used to change the route's name, which is useful for reverse routing
|
||||||
// inside views. Custom routes can be registered with `Handle`, which returns the *Route.
|
// inside views. Custom routes can be registered with `Handle`, which returns the *Route.
|
||||||
// This method exists mostly for the automatic method parsing based on the known patterns
|
// This method exists mostly for the automatic method parsing based on the known patterns
|
||||||
|
@ -208,10 +228,10 @@ func (c *ControllerActivator) Router() router.Party {
|
||||||
// A check for `nil` is necessary for unregistered methods.
|
// A check for `nil` is necessary for unregistered methods.
|
||||||
//
|
//
|
||||||
// See `Handle` too.
|
// See `Handle` too.
|
||||||
func (c *ControllerActivator) GetRoute(methodName string) *router.Route {
|
func (c *ControllerActivator) GetRoutes(methodName string) []*router.Route {
|
||||||
for name, route := range c.routes {
|
for name, routes := range c.routes {
|
||||||
if name == methodName {
|
if name == methodName {
|
||||||
return route
|
return routes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -274,10 +294,33 @@ func (c *ControllerActivator) parseMethod(m reflect.Method) {
|
||||||
// and a function name that belongs to the controller, it accepts
|
// and a function name that belongs to the controller, it accepts
|
||||||
// a forth, optionally, variadic parameter which is the before handlers.
|
// a forth, optionally, variadic parameter which is the before handlers.
|
||||||
//
|
//
|
||||||
// Just like `APIBuilder`, it returns the `*router.Route`, if failed
|
// Just like `Party#Handle`, it returns the `*router.Route`, if failed
|
||||||
// then it logs the errors and it returns nil, you can check the errors
|
// then it logs the errors and it returns nil, you can check the errors
|
||||||
// programmatically by the `APIBuilder#GetReporter`.
|
// programmatically by the `Party#GetReporter`.
|
||||||
func (c *ControllerActivator) Handle(method, path, funcName string, middleware ...context.Handler) *router.Route {
|
func (c *ControllerActivator) Handle(method, path, funcName string, middleware ...context.Handler) *router.Route {
|
||||||
|
routes := c.HandleMany(method, path, funcName, middleware...)
|
||||||
|
if len(routes) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleMany like `Handle` but can register more than one path and HTTP method routes
|
||||||
|
// separated by whitespace on the same controller's method.
|
||||||
|
// Keep note that if the controller's method input arguments are path parameters dependencies
|
||||||
|
// they should match with each of the given paths.
|
||||||
|
//
|
||||||
|
// Just like `Party#HandleMany`:, it returns the `[]*router.Routes`.
|
||||||
|
// Usage:
|
||||||
|
// func (*Controller) BeforeActivation(b mvc.BeforeActivation) {
|
||||||
|
// b.HandleMany("GET", "/path /path1" /path2", "HandlePath")
|
||||||
|
// }
|
||||||
|
func (c *ControllerActivator) HandleMany(method, path, funcName string, middleware ...context.Handler) []*router.Route {
|
||||||
|
return c.handleMany(method, path, funcName, true, middleware...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ControllerActivator) handleMany(method, path, funcName string, override bool, middleware ...context.Handler) []*router.Route {
|
||||||
if method == "" || path == "" || funcName == "" ||
|
if method == "" || path == "" || funcName == "" ||
|
||||||
c.isReservedMethod(funcName) {
|
c.isReservedMethod(funcName) {
|
||||||
// isReservedMethod -> if it's already registered
|
// isReservedMethod -> if it's already registered
|
||||||
|
@ -313,22 +356,30 @@ func (c *ControllerActivator) Handle(method, path, funcName string, middleware .
|
||||||
handler := c.handlerOf(m, funcDependencies)
|
handler := c.handlerOf(m, funcDependencies)
|
||||||
|
|
||||||
// register the handler now.
|
// register the handler now.
|
||||||
route := c.router.Handle(method, path, append(middleware, handler)...)
|
routes := c.router.HandleMany(method, path, append(middleware, handler)...)
|
||||||
if route == nil {
|
if routes == nil {
|
||||||
c.addErr(fmt.Errorf("MVC: unable to register a route for the path for '%s.%s'", c.fullName, funcName))
|
c.addErr(fmt.Errorf("MVC: unable to register a route for the path for '%s.%s'", c.fullName, funcName))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, r := range routes {
|
||||||
// change the main handler's name in order to respect the controller's and give
|
// change the main handler's name in order to respect the controller's and give
|
||||||
// a proper debug message.
|
// a proper debug message.
|
||||||
route.MainHandlerName = fmt.Sprintf("%s.%s", c.fullName, funcName)
|
r.MainHandlerName = fmt.Sprintf("%s.%s", c.fullName, funcName)
|
||||||
|
}
|
||||||
|
|
||||||
// add this as a reserved method name in order to
|
// add this as a reserved method name in order to
|
||||||
// be sure that the same func will not be registered again,
|
// be sure that the same route
|
||||||
// even if a custom .Handle later on.
|
// (method is allowed to be registered more than one on different routes - v11.2).
|
||||||
c.routes[funcName] = route
|
|
||||||
|
|
||||||
return route
|
existingRoutes, exist := c.routes[funcName]
|
||||||
|
if override || !exist {
|
||||||
|
c.routes[funcName] = routes
|
||||||
|
} else {
|
||||||
|
c.routes[funcName] = append(existingRoutes, routes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes
|
||||||
}
|
}
|
||||||
|
|
||||||
var emptyIn = []reflect.Value{}
|
var emptyIn = []reflect.Value{}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
|
|
||||||
"github.com/kataras/neffos"
|
"github.com/kataras/neffos"
|
||||||
|
|
||||||
"github.com/kataras/neffos/gobwas"
|
"github.com/kataras/neffos/gobwas"
|
||||||
"github.com/kataras/neffos/gorilla"
|
"github.com/kataras/neffos/gorilla"
|
||||||
"github.com/kataras/neffos/stackexchange/redis"
|
"github.com/kataras/neffos/stackexchange/redis"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user