Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 75b7d91

Browse filesBrowse files
committed
Added args to be passed to action using the Controller.Redirect
Added namespace to resolved path Renamed ServerHeader to Header (more backwards compatible) Updated intercept module to sort intercepts by "depth" this ensures that the most embedded intercept gets called first Added "appModule" to revel.Modules Added additional logging in router.splitactionpath Added setting template initialization engines to be read from template.engines
1 parent 31c9ac4 commit 75b7d91
Copy full SHA for 75b7d91

File tree

8 files changed

+210
-144
lines changed
Filter options

8 files changed

+210
-144
lines changed

‎controller.go

Copy file name to clipboardExpand all lines: controller.go
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ func (c *Controller) Redirect(val interface{}, args ...interface{}) Result {
329329
}
330330
return &RedirectToURLResult{fmt.Sprintf(url, args...)}
331331
}
332-
return &RedirectToActionResult{val}
332+
return &RedirectToActionResult{val, args}
333333
}
334334

335335
// This stats returns some interesting stats based on what is cached in memory

‎http.go

Copy file name to clipboardExpand all lines: http.go
+11-11Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
// Request is Revel's HTTP request object structure
2323
type Request struct {
2424
In ServerRequest
25-
ServerHeader *RevelHeader
25+
Header *RevelHeader
2626
ContentType string
2727
Format string // "html", "xml", "json", or "txt"
2828
AcceptLanguages AcceptLanguages
@@ -69,7 +69,7 @@ func NewResponse(w ServerResponse) (r *Response) {
6969

7070
// NewRequest returns a Revel's HTTP request instance with given HTTP instance
7171
func NewRequest(r ServerRequest) *Request {
72-
req := &Request{ServerHeader: &RevelHeader{}}
72+
req := &Request{Header: &RevelHeader{}}
7373
if r != nil {
7474
req.SetRequest(r)
7575
}
@@ -78,7 +78,7 @@ func NewRequest(r ServerRequest) *Request {
7878
func (req *Request) SetRequest(r ServerRequest) {
7979
req.In = r
8080
if h, e := req.In.Get(HTTP_SERVER_HEADER); e == nil {
81-
req.ServerHeader.Server = h.(ServerHeader)
81+
req.Header.Server = h.(ServerHeader)
8282
}
8383

8484
req.URL,_ = req.GetValue(HTTP_URL).(*url.URL)
@@ -91,8 +91,8 @@ func (req *Request) SetRequest(r ServerRequest) {
9191

9292
}
9393
func (req *Request) Cookie(key string) (ServerCookie, error) {
94-
if req.ServerHeader.Server != nil {
95-
return req.ServerHeader.Server.GetCookie(key)
94+
if req.Header.Server != nil {
95+
return req.Header.Server.GetCookie(key)
9696
}
9797
return nil, http.ErrNoCookie
9898
}
@@ -193,7 +193,7 @@ func (req *Request) Destroy() {
193193
req.Method = ""
194194
req.RemoteAddr = ""
195195
req.Host = ""
196-
req.ServerHeader.Destroy()
196+
req.Header.Destroy()
197197
req.URL = nil
198198
req.Form = nil
199199
req.MultipartForm = nil
@@ -221,15 +221,15 @@ func (resp *Response) Destroy() {
221221

222222
// UserAgent returns the client's User-Agent header string.
223223
func (r *Request) UserAgent() string {
224-
return r.ServerHeader.Get("User-Agent")
224+
return r.Header.Get("User-Agent")
225225
}
226226

227227
// Referer returns the client's Referer header string.
228228
func (req *Request) Referer() string {
229-
return req.ServerHeader.Get("Referer")
229+
return req.Header.Get("Referer")
230230
}
231231
func (req *Request) GetHttpHeader(key string) string {
232-
return req.ServerHeader.Get(key)
232+
return req.Header.Get(key)
233233
}
234234

235235
func (r *Request) GetValue(key int) (value interface{}) {
@@ -329,7 +329,7 @@ func (h *RevelHeader) GetAll(key string) (values []string) {
329329
// If none is specified, returns "text/html" by default.
330330
func ResolveContentType(req *Request) string {
331331

332-
contentType := req.ServerHeader.Get("Content-Type")
332+
contentType := req.Header.Get("Content-Type")
333333
if contentType == "" {
334334
return "text/html"
335335
}
@@ -412,7 +412,7 @@ func (al AcceptLanguages) String() string {
412412
// See the HTTP header fields specification
413413
// (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4) for more details.
414414
func ResolveAcceptLanguage(req *Request) AcceptLanguages {
415-
header := req.ServerHeader.Get("Accept-Language")
415+
header := req.Header.Get("Accept-Language")
416416
if header == "" {
417417
return req.AcceptLanguages
418418
}

‎intercept.go

Copy file name to clipboardExpand all lines: intercept.go
+40-12Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package revel
77
import (
88
"log"
99
"reflect"
10+
"sort"
1011
)
1112

1213
// An InterceptorFunc is functionality invoked by the framework BEFORE or AFTER
@@ -68,11 +69,11 @@ type Interception struct {
6869

6970
// Invoke performs the given interception.
7071
// val is a pointer to the App Controller.
71-
func (i Interception) Invoke(val reflect.Value) reflect.Value {
72+
func (i Interception) Invoke(val reflect.Value, target *reflect.Value) reflect.Value {
7273
var arg reflect.Value
7374
if i.function == nil {
7475
// If it's an InterceptorMethod, then we have to pass in the target type.
75-
arg = findTarget(val, i.target)
76+
arg = *target
7677
} else {
7778
// If it's an InterceptorFunc, then the type must be *Controller.
7879
// We can find that by following the embedded types up the chain.
@@ -115,7 +116,7 @@ func invokeInterceptors(when When, c *Controller) {
115116
)
116117

117118
for _, intc := range getInterceptors(when, app) {
118-
resultValue := intc.Invoke(app)
119+
resultValue := intc.Interceptor.Invoke(app, &intc.Target)
119120
if !resultValue.IsNil() {
120121
result = resultValue.Interface().(Result)
121122
}
@@ -154,6 +155,7 @@ func InterceptMethod(intc InterceptorMethod, when When) {
154155
log.Fatalln("Interceptor method should have signature like",
155156
"'func (c *AppController) example() revel.Result' but was", methodType)
156157
}
158+
157159
interceptors = append(interceptors, &Interception{
158160
When: when,
159161
method: intc,
@@ -162,38 +164,63 @@ func InterceptMethod(intc InterceptorMethod, when When) {
162164
})
163165
}
164166

165-
func getInterceptors(when When, val reflect.Value) []*Interception {
166-
result := []*Interception{}
167+
// This item is used to provide a sortable set to be returned to the caller. This ensures calls order is maintained
168+
//
169+
type interceptorItem struct {
170+
Interceptor *Interception
171+
Target reflect.Value
172+
Level int
173+
}
174+
type interceptorItemList []*interceptorItem
175+
func (a interceptorItemList) Len() int { return len(a) }
176+
func (a interceptorItemList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
177+
func (a interceptorItemList) Less(i, j int) bool { return a[i].Level < a[j].Level }
178+
type reverseInterceptorItemList []*interceptorItem
179+
func (a reverseInterceptorItemList) Len() int { return len(a) }
180+
func (a reverseInterceptorItemList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
181+
func (a reverseInterceptorItemList) Less(i, j int) bool { return a[i].Level > a[j].Level }
182+
func getInterceptors(when When, val reflect.Value) interceptorItemList {
183+
result := interceptorItemList{}
167184
for _, intc := range interceptors {
168185
if intc.When != when {
169186
continue
170187
}
171188

172-
if intc.interceptAll || findTarget(val, intc.target).IsValid() {
173-
result = append(result, intc)
189+
level,target := findTarget(val, intc.target)
190+
if intc.interceptAll || target.IsValid() {
191+
result = append(result, &interceptorItem{intc, target, level})
174192
}
175193
}
194+
195+
// Before is deepest to highest
196+
if when ==BEFORE {
197+
sort.Sort(result)
198+
} else {
199+
// Everything else is highest to deepest
200+
sort.Sort(reverseInterceptorItemList(result))
201+
}
176202
return result
177203
}
178204

179205
// Find the value of the target, starting from val and including embedded types.
180206
// Also, convert between any difference in indirection.
181207
// If the target couldn't be found, the returned Value will have IsValid() == false
182-
func findTarget(val reflect.Value, target reflect.Type) reflect.Value {
208+
func findTarget(val reflect.Value, target reflect.Type) (int, reflect.Value) {
183209
// Look through the embedded types (until we reach the *revel.Controller at the top).
184210
valueQueue := []reflect.Value{val}
211+
level := 0
185212
for len(valueQueue) > 0 {
186213
val, valueQueue = valueQueue[0], valueQueue[1:]
187214

188215
// Check if val is of a similar type to the target type.
189216
if val.Type() == target {
190-
return val
217+
return level,val
191218
}
192219
if val.Kind() == reflect.Ptr && val.Elem().Type() == target {
193-
return val.Elem()
220+
return level,val.Elem()
194221
}
195222
if target.Kind() == reflect.Ptr && target.Elem() == val.Type() {
196-
return val.Addr()
223+
return level,val.Addr()
197224
}
198225

199226
// If we reached the *revel.Controller and still didn't find what we were
@@ -212,7 +239,8 @@ func findTarget(val reflect.Value, target reflect.Type) reflect.Value {
212239
valueQueue = append(valueQueue, val.Field(i))
213240
}
214241
}
242+
level --
215243
}
216244

217-
return reflect.Value{}
245+
return level, reflect.Value{}
218246
}

‎intercept_test.go

Copy file name to clipboardExpand all lines: intercept_test.go
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ func testInterceptorController(t *testing.T, appControllerPtr reflect.Value, met
7777
}
7878
}
7979

80-
func testInterception(t *testing.T, intc *Interception, arg reflect.Value) {
81-
val := intc.Invoke(arg)
80+
func testInterception(t *testing.T, intc *interceptorItem, arg reflect.Value) {
81+
val := intc.Interceptor.Invoke(arg, &intc.Target)
8282
if !val.IsNil() {
8383
t.Errorf("Failed (%v): Expected nil got %v", intc, val)
8484
}

‎module.go

Copy file name to clipboardExpand all lines: module.go
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ func RegisterModuleInit(callback ModuleCallbackInterface) {
4747
func init() {
4848
AddInitEventHandler(func(typeOf int, value interface{}) (responseOf int) {
4949
if typeOf == REVEL_BEFORE_MODULES_LOADED {
50-
Modules = []*Module{}
50+
Modules = []*Module{appModule}
51+
appModule.Path = AppPath
5152
}
53+
5254
return
5355
})
5456
}
@@ -83,7 +85,7 @@ func (m *Module) AddController(ct *ControllerType) {
8385
// Only to be used on initialization
8486
func ModuleFromPath(path string, addGopathToPath bool) (module *Module) {
8587
gopathList := filepath.SplitList(build.Default.GOPATH)
86-
// ignore the vendor folder
88+
// Strip away the vendor folder
8789
if i := strings.Index(path, "/vendor/"); i > 0 {
8890
path = path[i+len("vendor/"):]
8991
}

‎results.go

Copy file name to clipboardExpand all lines: results.go
+25-4Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,11 @@ func (r *RedirectToURLResult) Apply(req *Request, resp *Response) {
432432

433433
type RedirectToActionResult struct {
434434
val interface{}
435+
args []interface{}
435436
}
436437

437438
func (r *RedirectToActionResult) Apply(req *Request, resp *Response) {
438-
url, err := getRedirectURL(r.val)
439+
url, err := getRedirectURL(r.val, r.args)
439440
if err != nil {
440441
resultsLog.Error("Apply: Couldn't resolve redirect", "error", err)
441442
ErrorResult{Error: err}.Apply(req, resp)
@@ -445,7 +446,7 @@ func (r *RedirectToActionResult) Apply(req *Request, resp *Response) {
445446
resp.WriteHeader(http.StatusFound, "")
446447
}
447448

448-
func getRedirectURL(item interface{}) (string, error) {
449+
func getRedirectURL(item interface{}, args []interface{}) (string, error) {
449450
// Handle strings
450451
if url, ok := item.(string); ok {
451452
return url, nil
@@ -466,8 +467,28 @@ func getRedirectURL(item interface{}) (string, error) {
466467
if recvType.Kind() == reflect.Ptr {
467468
recvType = recvType.Elem()
468469
}
469-
action := recvType.Name() + "." + method.Name
470-
actionDef := MainRouter.Reverse(action, make(map[string]string))
470+
module := ModuleFromPath(recvType.PkgPath(),true)
471+
println("Returned ", module)
472+
action := module.Namespace() + recvType.Name() + "." + method.Name
473+
// Fetch the action path to get the defaults
474+
pathData, found := splitActionPath(nil, action, true)
475+
if !found {
476+
return "", fmt.Errorf("Unable to redirect '%s', expected 'Controller.Action'", action)
477+
}
478+
479+
// Build the map for the router to reverse
480+
// Unbind the arguments.
481+
argsByName := make(map[string]string)
482+
// Bind any static args first
483+
fixedParams := len(pathData.FixedParamsByName)
484+
methodType := pathData.TypeOfController.Method(pathData.MethodName)
485+
486+
for i, argValue := range args {
487+
Unbind(argsByName, methodType.Args[i+fixedParams].Name, argValue)
488+
}
489+
490+
491+
actionDef := MainRouter.Reverse(action, argsByName)
471492
if actionDef == nil {
472493
return "", errors.New("no route for action " + action)
473494
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.