Skip to content

Commit 187e480

Browse files
committed
Small refactor of the middleware code + tests
This is a preparation for further middleware improvements.
1 parent 5fe7b58 commit 187e480

File tree

3 files changed

+80
-15
lines changed

3 files changed

+80
-15
lines changed

rest/handler.go

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,6 @@ import (
88
"strings"
99
)
1010

11-
// HandlerFunc defines the handler function. It is the go-json-rest equivalent of http.HandlerFunc.
12-
type HandlerFunc func(ResponseWriter, *Request)
13-
14-
// Middleware defines the interface that objects must implement in order to wrap a HandlerFunc and
15-
// be used in the middleware stack.
16-
type Middleware interface {
17-
MiddlewareFunc(handler HandlerFunc) HandlerFunc
18-
}
19-
2011
// ResourceHandler implements the http.Handler interface and acts a router for the defined Routes.
2112
// The defaults are intended to be developemnt friendly, for production you may want
2213
// to turn on gzip and disable the JSON indentation for instance.
@@ -140,12 +131,9 @@ func (rh *ResourceHandler) instantiateMiddlewares() {
140131
rh.PreRoutingMiddlewares...,
141132
)
142133

143-
handler := rh.app()
144-
for i := len(middlewares) - 1; i >= 0; i-- {
145-
handler = middlewares[i].MiddlewareFunc(handler)
146-
}
147-
148-
rh.handlerFunc = rh.adapter(handler)
134+
rh.handlerFunc = rh.adapter(
135+
wrapMiddlewares(middlewares, rh.app()),
136+
)
149137
}
150138

151139
// Middleware that handles the transition between http and rest objects.

rest/middleware.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package rest
2+
3+
// HandlerFunc defines the handler function. It is the go-json-rest equivalent of http.HandlerFunc.
4+
type HandlerFunc func(ResponseWriter, *Request)
5+
6+
// Middleware defines the interface that objects must implement in order to wrap a HandlerFunc and
7+
// be used in the middleware stack.
8+
type Middleware interface {
9+
MiddlewareFunc(handler HandlerFunc) HandlerFunc
10+
}
11+
12+
// wrapMiddlewares calls the MiddlewareFunc in the reverse order and returns an HandlerFunc ready
13+
// to be executed.
14+
func wrapMiddlewares(middlewares []Middleware, handler HandlerFunc) HandlerFunc {
15+
wrapped := handler
16+
for i := len(middlewares) - 1; i >= 0; i-- {
17+
wrapped = middlewares[i].MiddlewareFunc(wrapped)
18+
}
19+
return wrapped
20+
}

rest/middleware_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package rest
2+
3+
import (
4+
"testing"
5+
)
6+
7+
type testMiddleware struct {
8+
name string
9+
}
10+
11+
func (mw *testMiddleware) MiddlewareFunc(handler HandlerFunc) HandlerFunc {
12+
return func(w ResponseWriter, r *Request) {
13+
if r.Env["BEFORE"] == nil {
14+
r.Env["BEFORE"] = mw.name
15+
} else {
16+
r.Env["BEFORE"] = r.Env["BEFORE"].(string) + mw.name
17+
}
18+
handler(w, r)
19+
if r.Env["AFTER"] == nil {
20+
r.Env["AFTER"] = mw.name
21+
} else {
22+
r.Env["AFTER"] = r.Env["AFTER"].(string) + mw.name
23+
}
24+
}
25+
}
26+
27+
func TestWrapMiddlewares(t *testing.T) {
28+
29+
a := &testMiddleware{"A"}
30+
b := &testMiddleware{"B"}
31+
c := &testMiddleware{"C"}
32+
33+
app := func(w ResponseWriter, r *Request) {
34+
// do nothing
35+
}
36+
37+
handlerFunc := wrapMiddlewares([]Middleware{a, b, c}, app)
38+
39+
// fake request
40+
r := &Request{
41+
nil,
42+
nil,
43+
map[string]interface{}{},
44+
}
45+
46+
handlerFunc(nil, r)
47+
48+
before := r.Env["BEFORE"].(string)
49+
if before != "ABC" {
50+
t.Error("middleware executed in the wrong order, expected ABC")
51+
}
52+
53+
after := r.Env["AFTER"].(string)
54+
if after != "CBA" {
55+
t.Error("middleware executed in the wrong order, expected CBA")
56+
}
57+
}

0 commit comments

Comments
 (0)