-
Notifications
You must be signed in to change notification settings - Fork 1
/
middleware.go
159 lines (147 loc) · 6.27 KB
/
middleware.go
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
package nvelope
import (
"net/http"
"github.com/muir/nject"
)
// MiddlewareBaseWriter acts as a translator. In the Go world, there
// are a bunch of packages that expect to use the wrapping
//
// func(http.HandlerFunc) http.HandlerFunc
//
// pattern. The func(http.HandlerFunc) http.HandlerFunc pattern is harder to
// use and not as expressive as the patterns supported by
// npoint and nvelope, but there may be code written
// with the func(http.HandlerFunc) http.HandlerFunc pattern that you want to use with
// npoint and nvelope.
//
// MiddlewareBaseWriter converts existing func(http.HandlerFunc) http.HandlerFunc functions so that
// they're compatible with nject. Because Middleware may wrap
// http.ResponseWriter, it should be used earlier in the injection
// chain than InjectWriter so that InjectWriter gets the already-wrapped
// http.ResponseWriter. Use MiddlewareBaseWriter if you suspect that the
// middleware you're wrapping replaces the writer.
func MiddlewareBaseWriter(m ...func(http.HandlerFunc) http.HandlerFunc) nject.Provider {
combined := combineMiddleware(m)
return nject.Required(nject.Provide("wrapped-func(http.HandlerFunc) http.HandlerFunc-base",
func(inner func(w http.ResponseWriter, r *http.Request), w http.ResponseWriter, r *http.Request) {
combined(inner)(w, r)
}))
}
// MiddlewareDeferredWriter acts as a translator. In the Go world, there
// are a bunch of packages that expect to use the wrapping
//
// func(http.HandlerFunc) http.HandlerFunc
//
// pattern. The func(http.HandlerFunc) http.HandlerFunc pattern is harder to
// use and not as expressive as the patterns supported by
// npoint and nvelope, but there may be code written
// with the func(http.HandlerFunc) http.HandlerFunc pattern that you want to use with
// npoint and nvelope.
//
// MiddlewareDeferredWriter converts existing func(http.HandlerFunc) http.HandlerFunc functions so that
// they're compatible with nject. MiddlewareDeferredWriter injects a
// DeferredWriter into the the func(http.HandlerFunc) http.HandlerFunc handler chain. If the chain
// replaces the writer, there will be two writers in play at once and
// results may be inconsistent. MiddlewareDeferredWriter must be used
// after InjectWriter. Use MiddlewareDeferredWriter if you know that the middleware
// you're wrapping does not replace the writer.
func MiddlewareDeferredWriter(m ...func(http.HandlerFunc) http.HandlerFunc) nject.Provider {
combined := combineMiddleware(m)
return nject.Required(nject.Provide("wrapped-func(http.HandlerFunc) http.HandlerFunc-deferred",
func(inner func(w http.ResponseWriter, r *http.Request), w *DeferredWriter, r *http.Request) {
combined(inner)(http.ResponseWriter(w), r)
}))
}
func combineMiddleware(m []func(http.HandlerFunc) http.HandlerFunc) func(http.HandlerFunc) http.HandlerFunc {
switch len(m) {
case 0:
return func(h http.HandlerFunc) http.HandlerFunc {
return h
}
case 1:
return m[0]
default:
combined := m[len(m)-1]
for i := len(m) - 2; i >= 0; i-- {
f := m[i]
c := combined
combined = func(h http.HandlerFunc) http.HandlerFunc {
return f(c(h))
}
}
return combined
}
}
// MiddlewareHandlerBaseWriter acts as a translator. In the Go world, there
// are a bunch of packages that expect to use the wrapping
//
// func(http.Handler) http.Handler
//
// pattern. The func(http.HandlerFunc) http.HandlerFunc pattern is harder to
// use and not as expressive as the patterns supported by
// npoint and nvelope, but there may be code written
// with the func(http.HandlerFunc) http.HandlerFunc pattern that you want to use with
// npoint and nvelope.
//
// MiddlewareHandlerBaseWriter converts existing func(http.Handler) http.Handler functions so that
// they're compatible with nject. Because Middleware may wrap
// http.ResponseWriter, it should be used earlier in the injection
// chain than InjectWriter so that InjectWriter gets the already-wrapped
// http.ResponseWriter. Use MiddlewareBaseWriter if you suspect that the
// middleware you're wrapping replaces the writer.
func MiddlewareHandlerBaseWriter(m ...func(http.Handler) http.Handler) nject.Provider {
combined := combineHandlerMiddleware(m)
return nject.Required(nject.Provide("wrapped-func(http.Handler) http.Handler-base",
func(inner func(w http.ResponseWriter, r *http.Request), w http.ResponseWriter, r *http.Request) {
combined(inner)(w, r)
}))
}
// MiddlewareHandlerDeferredWriter acts as a translator. In the Go world, there
// are a bunch of packages that expect to use the wrapping
//
// func(http.Handler) http.Handler
//
// pattern. The func(http.Handler) http.Handler pattern is harder to
// use and not as expressive as the patterns supported by
// npoint and nvelope, but there may be code written
// with the func(http.Handler) http.Handler pattern that you want to use with
// npoint and nvelope.
//
// MiddlewareHandlerDeferredWriter converts existing func(http.Handler) http.Handler functions so that
// they're compatible with nject. MiddlewareHandlerDeferredWriter injects a
// DeferredWriter into the the func(http.Handler) http.Handler handler chain. If the chain
// replaces the writer, there will be two writers in play at once and
// results may be inconsistent. MiddlewareHandlerDeferredWriter must be used
// after InjectWriter. Use MiddlewareHandlerDeferredWriter if you know that the middleware
// you're wrapping does not replace the writer.
func MiddlewareHandlerDeferredWriter(m ...func(http.Handler) http.Handler) nject.Provider {
combined := combineHandlerMiddleware(m)
return nject.Required(nject.Provide("wrapped-func(http.Handler) http.Handler-deferred",
func(inner func(w http.ResponseWriter, r *http.Request), w *DeferredWriter, r *http.Request) {
combined(inner)(http.ResponseWriter(w), r)
}))
}
func combineHandlerMiddleware(m []func(http.Handler) http.Handler) func(http.HandlerFunc) http.HandlerFunc {
switch len(m) {
case 0:
return func(h http.HandlerFunc) http.HandlerFunc {
return h
}
case 1:
return func(h http.HandlerFunc) http.HandlerFunc {
return m[0](h).ServeHTTP
}
default:
combined := func(h http.HandlerFunc) http.HandlerFunc {
return m[len(m)-1](h).ServeHTTP
}
for i := len(m) - 2; i >= 0; i-- {
f := m[i]
c := combined
combined = func(h http.HandlerFunc) http.HandlerFunc {
return f(c(h)).ServeHTTP
}
}
return combined
}
}