/
handler_manager.go
158 lines (133 loc) · 3.5 KB
/
handler_manager.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
package pipehub
import (
"context"
"fmt"
"net/http"
"reflect"
"strings"
"github.com/pkg/errors"
)
type handlerManager struct {
client *Client
handlers []handler
action struct {
notFound http.HandlerFunc
panik func(http.Handler) http.Handler
}
}
func (h *handlerManager) init() error {
if err := h.initAction(); err != nil {
return errors.Wrap(err, "init action error")
}
if err := h.initHandlers(); err != nil {
return errors.Wrap(err, "init handlers error")
}
return nil
}
// essa função tem que ser genérica o suficiente pra podermos usar pro not found e pro panic.
func (h *handlerManager) initAction() error {
notFoundAction, err := h.initFunc(h.client.cfg.Server.Action.NotFound)
if err != nil {
return errors.Wrap(err, "not found action initialization error")
}
h.action.notFound = notFoundAction
panik, _, err := h.initMiddleware(h.client.cfg.Server.Action.Panic)
if err != nil {
return errors.Wrap(err, "panic initialization error")
}
h.action.panik = panik
return nil
}
func (h *handlerManager) initHandlers() error {
for _, host := range h.client.cfg.Host {
middleware, rawHandler, err := h.initMiddleware(host.Handler)
if err != nil {
return errors.Wrap(err, "middleware initialization error")
}
hh := handler{
name: host.Handler,
endpoint: host.Endpoint,
instance: rawHandler.instance,
alias: rawHandler.alias,
fn: middleware,
}
h.handlers = append(h.handlers, hh)
}
return nil
}
func (h handlerManager) initGeneric(id string) (interface{}, handler, error) {
if id == "" {
return nil, handler{}, nil
}
handlers, err := fetchHandlers()
if err != nil {
return nil, handler{}, errors.Wrap(err, "fetch handlers error")
}
for _, rawHandler := range handlers {
if !strings.HasPrefix(id, rawHandler.alias+".") {
continue
}
fragments := strings.Split(id, ".")
if len(fragments) != 2 {
return nil, handler{}, fmt.Errorf("invalid func '%s'", id)
}
value := reflect.ValueOf(rawHandler.instance).MethodByName(fragments[1])
if !value.IsValid() {
continue
}
rawFn := value.Interface()
return rawFn, rawHandler, nil
}
return nil, handler{}, nil
}
func (h handlerManager) initFunc(id string) (http.HandlerFunc, error) {
rawFn, _, err := h.initGeneric(id)
if err != nil {
return nil, err
}
if rawFn == nil {
return nil, nil
}
fn, ok := rawFn.(func(http.ResponseWriter, *http.Request))
if !ok {
return nil, fmt.Errorf("invalid func '%s'", id)
}
return fn, nil
}
func (h handlerManager) initMiddleware(id string) (func(http.Handler) http.Handler, handler, error) {
rawFn, rawHandler, err := h.initGeneric(id)
if err != nil {
return nil, handler{}, err
}
if rawFn == nil {
return nil, handler{}, nil
}
fn, ok := rawFn.(func(http.Handler) http.Handler)
if !ok {
return nil, handler{}, fmt.Errorf("invalid func '%s'", id)
}
return fn, rawHandler, nil
}
func (h handlerManager) fetch(name string) (handler, error) {
for _, handler := range h.handlers {
if handler.name == name {
return handler, nil
}
}
return handler{}, fmt.Errorf("handler '%s' not found", name)
}
func (h *handlerManager) close(ctx context.Context) error {
for _, handler := range h.handlers {
if err := handler.instance.Close(ctx); err != nil {
return errors.Wrap(err, "error closing handler")
}
}
return nil
}
func newHandlerManager(c *Client) (*handlerManager, error) {
h := handlerManager{client: c}
if err := h.init(); err != nil {
return nil, errors.Wrap(err, "initialization error")
}
return &h, nil
}