/usr/share/gocode/src/github.com/revel/revel/filterconfig.go is in golang-github-revel-revel-dev 0.12.0+dfsg-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | package revel
import (
"reflect"
"strings"
)
// Map from "Controller" or "Controller.Method" to the Filter chain
var filterOverrides = make(map[string][]Filter)
// FilterConfigurator allows the developer configure the filter chain on a
// per-controller or per-action basis. The filter configuration is applied by
// the FilterConfiguringFilter, which is itself a filter stage. For example,
//
// Assuming:
// Filters = []Filter{
// RouterFilter,
// FilterConfiguringFilter,
// SessionFilter,
// ActionInvoker,
// }
//
// Add:
// FilterAction(App.Action).
// Add(OtherFilter)
//
// => RouterFilter, FilterConfiguringFilter, SessionFilter, OtherFilter, ActionInvoker
//
// Remove:
// FilterAction(App.Action).
// Remove(SessionFilter)
//
// => RouterFilter, FilterConfiguringFilter, OtherFilter, ActionInvoker
//
// Insert:
// FilterAction(App.Action).
// Insert(OtherFilter, revel.BEFORE, SessionFilter)
//
// => RouterFilter, FilterConfiguringFilter, OtherFilter, SessionFilter, ActionInvoker
//
// Filter modifications may be combined between Controller and Action. For example:
// FilterController(App{}).
// Add(Filter1)
// FilterAction(App.Action).
// Add(Filter2)
//
// .. would result in App.Action being filtered by both Filter1 and Filter2.
//
// Note: the last filter stage is not subject to the configurator. In
// particular, Add() adds a filter to the second-to-last place.
type FilterConfigurator struct {
key string // e.g. "App", "App.Action"
controllerName string // e.g. "App"
}
func newFilterConfigurator(controllerName, methodName string) FilterConfigurator {
if methodName == "" {
return FilterConfigurator{controllerName, controllerName}
}
return FilterConfigurator{controllerName + "." + methodName, controllerName}
}
// FilterController returns a configurator for the filters applied to all
// actions on the given controller instance. For example:
// FilterAction(MyController{})
func FilterController(controllerInstance interface{}) FilterConfigurator {
t := reflect.TypeOf(controllerInstance)
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
return newFilterConfigurator(t.Name(), "")
}
// FilterAction returns a configurator for the filters applied to the given
// controller method. For example:
// FilterAction(MyController.MyAction)
func FilterAction(methodRef interface{}) FilterConfigurator {
var (
methodValue = reflect.ValueOf(methodRef)
methodType = methodValue.Type()
)
if methodType.Kind() != reflect.Func || methodType.NumIn() == 0 {
panic("Expecting a controller method reference (e.g. Controller.Action), got a " +
methodType.String())
}
controllerType := methodType.In(0)
method := FindMethod(controllerType, methodValue)
if method == nil {
panic("Action not found on controller " + controllerType.Name())
}
for controllerType.Kind() == reflect.Ptr {
controllerType = controllerType.Elem()
}
return newFilterConfigurator(controllerType.Name(), method.Name)
}
// Add the given filter in the second-to-last position in the filter chain.
// (Second-to-last so that it is before ActionInvoker)
func (conf FilterConfigurator) Add(f Filter) FilterConfigurator {
conf.apply(func(fc []Filter) []Filter {
return conf.addFilter(f, fc)
})
return conf
}
func (conf FilterConfigurator) addFilter(f Filter, fc []Filter) []Filter {
return append(fc[:len(fc)-1], f, fc[len(fc)-1])
}
// Remove a filter from the filter chain.
func (conf FilterConfigurator) Remove(target Filter) FilterConfigurator {
conf.apply(func(fc []Filter) []Filter {
return conf.rmFilter(target, fc)
})
return conf
}
func (conf FilterConfigurator) rmFilter(target Filter, fc []Filter) []Filter {
for i, f := range fc {
if FilterEq(f, target) {
return append(fc[:i], fc[i+1:]...)
}
}
return fc
}
// Insert a filter into the filter chain before or after another.
// This may be called with the BEFORE or AFTER constants, for example:
// revel.FilterAction(App.Index).
// Insert(MyFilter, revel.BEFORE, revel.ActionInvoker).
// Insert(MyFilter2, revel.AFTER, revel.PanicFilter)
func (conf FilterConfigurator) Insert(insert Filter, where When, target Filter) FilterConfigurator {
if where != BEFORE && where != AFTER {
panic("where must be BEFORE or AFTER")
}
conf.apply(func(fc []Filter) []Filter {
return conf.insertFilter(insert, where, target, fc)
})
return conf
}
func (conf FilterConfigurator) insertFilter(insert Filter, where When, target Filter, fc []Filter) []Filter {
for i, f := range fc {
if FilterEq(f, target) {
if where == BEFORE {
return append(fc[:i], append([]Filter{insert}, fc[i:]...)...)
} else {
return append(fc[:i+1], append([]Filter{insert}, fc[i+1:]...)...)
}
}
}
return fc
}
// getChain returns the filter chain that applies to the given controller or
// action. If no overrides are configured, then a copy of the default filter
// chain is returned.
func (conf FilterConfigurator) getChain() []Filter {
var filters []Filter
if filters = getOverrideChain(conf.controllerName, conf.key); filters == nil {
// The override starts with all filters after FilterConfiguringFilter
for i, f := range Filters {
if FilterEq(f, FilterConfiguringFilter) {
filters = make([]Filter, len(Filters)-i-1)
copy(filters, Filters[i+1:])
break
}
}
if filters == nil {
panic("FilterConfiguringFilter not found in revel.Filters.")
}
}
return filters
}
// apply applies the given functional change to the filter overrides.
// No other function modifies the filterOverrides map.
func (conf FilterConfigurator) apply(f func([]Filter) []Filter) {
// Updates any actions that have had their filters overridden, if this is a
// Controller configurator.
if conf.controllerName == conf.key {
for k, v := range filterOverrides {
if strings.HasPrefix(k, conf.controllerName+".") {
filterOverrides[k] = f(v)
}
}
}
// Update the Controller or Action overrides.
filterOverrides[conf.key] = f(conf.getChain())
}
// FilterEq returns true if the two filters reference the same filter.
func FilterEq(a, b Filter) bool {
return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer()
}
// FilterConfiguringFilter is a filter stage that customizes the remaining
// filter chain for the action being invoked.
func FilterConfiguringFilter(c *Controller, fc []Filter) {
if newChain := getOverrideChain(c.Name, c.Action); newChain != nil {
newChain[0](c, newChain[1:])
return
}
fc[0](c, fc[1:])
}
// getOverrideChain retrieves the overrides for the action that is set
func getOverrideChain(controllerName, action string) []Filter {
if newChain, ok := filterOverrides[action]; ok {
return newChain
}
if newChain, ok := filterOverrides[controllerName]; ok {
return newChain
}
return nil
}
|