-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwrapper.go
96 lines (86 loc) · 2.26 KB
/
wrapper.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
package httpwrap
import (
"net/http"
"reflect"
)
// Wrapper implements the http.Handler interface, wrapping the handlers
// that are passed in.
type Wrapper struct {
befores []beforeFn
after *afterFn
construct RequestReader
}
// New creates a new Wrapper object. This wrapper object will not interact in any way
// with the http request and response writer.
func New() Wrapper {
return Wrapper{
construct: emptyRequestReader,
}
}
// WithRequestReader returns a new wrapper with the given RequestReader function.
func (w Wrapper) WithRequestReader(cons RequestReader) Wrapper {
w.construct = cons
return w
}
// Before adds a new function that will execute before the main handler. The chain
// of befores will end if a before returns a non-nil error value.
func (w Wrapper) Before(fns ...any) Wrapper {
befores := make([]beforeFn, len(w.befores)+len(fns))
copy(befores, w.befores)
for i, before := range fns {
helper, err := newBefore(before)
if err != nil {
panic(err)
}
befores[i+len(w.befores)] = helper
}
w.befores = befores
return w
}
// Finally sets the last function that will execute during a request. This function gets
// invoked with the response object and the possible error returned from the main
// endpoint function.
func (w Wrapper) Finally(fn any) Wrapper {
after, err := newAfter(fn)
if err != nil {
panic(err)
}
w.after = &after
return w
}
// Wrap sets the main handling function to process requests. This Wrap function must
// be called to get an `http.Handler` type.
func (w Wrapper) Wrap(fn any) http.Handler {
main, err := newMain(fn)
if err != nil {
panic(err)
}
return wrappedHttpHandler{
Wrapper: w,
main: main,
}
}
// wrappedHttpHandler is a Wrapper that implements `http.Handler`.
type wrappedHttpHandler struct {
Wrapper
main mainFn
}
// ServeHTTP implements `http.Handler`.
func (h wrappedHttpHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
ctx := newRunCtx(rw, req, h.construct)
err := h.serveBefores(ctx)
if err == nil {
ctx.response = reflect.ValueOf(h.main.run(ctx))
}
if h.after != nil {
h.after.run(ctx)
}
}
func (h wrappedHttpHandler) serveBefores(ctx *runctx) error {
for _, before := range h.befores {
if err := before.run(ctx); err != nil {
return err
}
}
return nil
}