An Interceptor is a function that is invoked by the framework BEFORE
or AFTER
an action invocation. It allows a form ofAspect Oriented Programming,which is useful for some common concerns such as:
- Request logging
- Error handling
- Statistics logging
Authentication handling
In Revel, an interceptor can take one of three forms:- A Method Interceptor
- A Controller Auto Interceptor using the revel.BeforeAfterFilter filter
An Interceptor has an intercept point in the request (When) and returns a Result ornil
.
NOTE: Interceptors are called in the order that they are added.
Function Interceptor
- A function meeting the InterceptorFunc interface.
- Does not have access to the specific Controller invoked.
- May be applied to any / all Controllers in an application (by adding lines of code).
// simple example or user authfunccheckUser(c*revel.Controller)revel.Result{ifuser:=MyCheckAuth(c);user==nil{c.Flash.Error("Please log in first")returnc.Redirect(App.Index)}returnnil}funcdoNothing(c*revel.Controller)revel.Result{returnnil}funcinit(){revel.InterceptFunc(checkUser,revel.BEFORE,&App{})revel.InterceptFunc(doNothing,revel.AFTER,&App{})revel.InterceptFunc(checkUser,revel.BEFORE,&AnotherController{})}
Method Interceptor
- A InterceptorMethod method accepting no arguments and returning a revel.Result.
- May only intercept calls to the boundController.
- May modify the invoked controller as desired.
- A method interceptor signature may have one of these two forms, or both:
- func (c AppController) example() revel.Result
- func (c *AppController) example() revel.Result // pointer
// simple method examplefunc(cHotels)checkUser()revel.Result{ifuser:=connected(c);user==nil{c.Flash.Error("Please log in first")returnc.Redirect(App.Index)}returnnil}funcinit(){revel.InterceptMethod(Hotels.checkUser,revel.BEFORE)revel.InterceptMethod(Room.checkVacant,revel.BEFORE)}
Controller Auto Interceptor
Controllers that have methods named Before
,After
,Finally
,Panic
, will be called in the same manner as the interceptor does. The method signature is a little different then normal to allow for method Overriding and cascades. ie if Application has GorpController controller embedded inside it and both define the Before
method then what happens is the GorpController.Before
is invoked before the Application.Before
. The method signature must match the following syntax
func (c Application) Before() (r revel.Result, a Application) {
...
func (c *GorpController) Before() (result revel.Result, controller *GorpController) {
Notice along with the revel.Result we return the Controller type. This is so when the application starts up it can determine which method belongs to what field in the controller (currently Go does not tell you this information). These work identical to the revel.Interceptors without any configuration.
On the Before
method the deepest embedded struct with the Before
method is run first, then the next deepest and so on until the top level. After
, Finally
, Panic
are run from the top down
Controller Auto Interceptor Implementation
Add the filter revel.BeforeAfterFilter
to revel.Filters on app/init.go. Ensure your function names match func (c Application) Before() (r revel.Result, a Application)
Intercept Times
An interceptor can be registered to run at four points in the request lifecycle; defined in When():
- BEFORE
- After the request has been routed, the session, flash, and parameters decoded, but before the action has been invoked.
- AFTER
- After the request has returned a Result, but before that Result has been applied. These interceptors are not invoked if the action panicked.
- PANIC
- After a panic exits an action or is raised from applying the returned Result.
- FINALLY
Results
Interceptors typically return nil
, in which case the request continues tobe processed without interruption.
The effect of returning a non-nil
revel.Result depends on When() the interceptorwas invoked.
- BEFORE
- No further interceptors are invoked, and neither is the action.
- AFTER
- All interceptors are still run.
- PANIC
- All interceptors are still run.
FINALLY
- All interceptors are still run.
In all cases, any returned Result will take the place of any existing Result.
- All interceptors are still run.
However, in the BEFORE case, the returned Result is guaranteed to be final,
- While in the AFTER case it is possible that a further interceptor could emit its own Result.
GoDoc Reference
GitHub Labels
- Issues: topic-controller
- Pull Requests: topic-controller