-
Notifications
You must be signed in to change notification settings - Fork 71
/
Copy pathbase.go
150 lines (124 loc) · 4.71 KB
/
base.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
package handlers
import (
"context"
"fmt"
"net/http"
"github.com/nyaruka/courier"
"github.com/nyaruka/gocommon/httpx"
)
var defaultRedactConfigKeys = []string{courier.ConfigAuthToken, courier.ConfigAPIKey, courier.ConfigSecret, courier.ConfigPassword, courier.ConfigSendAuthorization}
// BaseHandler is the base class for most handlers, it just stored the server, name and channel type for the handler
type BaseHandler struct {
channelType courier.ChannelType
name string
server courier.Server
backend courier.Backend
uuidChannelRouting bool
redactConfigKeys []string
}
// NewBaseHandler returns a newly constructed BaseHandler with the passed in parameters
func NewBaseHandler(channelType courier.ChannelType, name string, options ...func(*BaseHandler)) BaseHandler {
h := &BaseHandler{
channelType: channelType,
name: name,
uuidChannelRouting: true,
redactConfigKeys: defaultRedactConfigKeys,
}
for _, o := range options {
o(h)
}
return *h
}
func DisableUUIDRouting() func(*BaseHandler) {
return func(s *BaseHandler) {
s.uuidChannelRouting = false
}
}
func WithRedactConfigKeys(keys ...string) func(*BaseHandler) {
return func(s *BaseHandler) {
s.redactConfigKeys = keys
}
}
// SetServer can be used to change the server on a BaseHandler
func (h *BaseHandler) SetServer(server courier.Server) {
h.server = server
h.backend = server.Backend()
}
// Server returns the server instance on the BaseHandler
func (h *BaseHandler) Server() courier.Server {
return h.server
}
// Backend returns the backend instance on the BaseHandler
func (h *BaseHandler) Backend() courier.Backend {
return h.backend
}
// ChannelType returns the channel type that this handler deals with
func (h *BaseHandler) ChannelType() courier.ChannelType {
return h.channelType
}
// ChannelName returns the name of the channel this handler deals with
func (h *BaseHandler) ChannelName() string {
return h.name
}
// UseChannelRouteUUID returns whether the router should use the channel UUID in the URL path
func (h *BaseHandler) UseChannelRouteUUID() bool {
return h.uuidChannelRouting
}
func (h *BaseHandler) RedactValues(ch courier.Channel) []string {
if ch == nil {
return nil
}
vals := make([]string, 0, len(h.redactConfigKeys))
for _, k := range h.redactConfigKeys {
v := ch.StringConfigForKey(k, "")
if v != "" {
vals = append(vals, v)
}
}
return vals
}
// GetChannel returns the channel
func (h *BaseHandler) GetChannel(ctx context.Context, r *http.Request) (courier.Channel, error) {
uuid := courier.ChannelUUID(r.PathValue("uuid"))
return h.backend.GetChannel(ctx, h.ChannelType(), uuid)
}
// RequestHTTP does the given request, logging the trace, and returns the response
func (h *BaseHandler) RequestHTTP(req *http.Request, clog *courier.ChannelLog) (*http.Response, []byte, error) {
return h.RequestHTTPWithClient(h.backend.HttpClient(true), req, clog)
}
// RequestHTTP does the given request, logging the trace, and returns the response
func (h *BaseHandler) RequestHTTPInsecure(req *http.Request, clog *courier.ChannelLog) (*http.Response, []byte, error) {
return h.RequestHTTPWithClient(h.backend.HttpClient(false), req, clog)
}
// RequestHTTP does the given request using the given client, logging the trace, and returns the response
func (h *BaseHandler) RequestHTTPWithClient(client *http.Client, req *http.Request, clog *courier.ChannelLog) (*http.Response, []byte, error) {
var resp *http.Response
var body []byte
req.Header.Set("User-Agent", fmt.Sprintf("Courier/%s", h.server.Config().Version))
trace, err := httpx.DoTrace(client, req, nil, h.backend.HttpAccess(), 0)
if trace != nil {
clog.HTTP(trace)
resp = trace.Response
body = trace.ResponseBody
}
if err != nil {
return nil, nil, err
}
return resp, body, nil
}
// WriteStatusSuccessResponse writes a success response for the statuses
func (h *BaseHandler) WriteStatusSuccessResponse(ctx context.Context, w http.ResponseWriter, statuses []courier.StatusUpdate) error {
return courier.WriteStatusSuccess(w, statuses)
}
// WriteMsgSuccessResponse writes a success response for the messages
func (h *BaseHandler) WriteMsgSuccessResponse(ctx context.Context, w http.ResponseWriter, msgs []courier.MsgIn) error {
return courier.WriteMsgSuccess(w, msgs)
}
// WriteRequestError writes the passed in error to our response writer
func (h *BaseHandler) WriteRequestError(ctx context.Context, w http.ResponseWriter, err error) error {
return courier.WriteError(w, http.StatusBadRequest, err)
}
// WriteRequestIgnored writes an ignored payload to our response writer
func (h *BaseHandler) WriteRequestIgnored(ctx context.Context, w http.ResponseWriter, details string) error {
return courier.WriteIgnored(w, details)
}