-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathdir-lookup-http-handler.go
183 lines (160 loc) · 5.49 KB
/
dir-lookup-http-handler.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package bifrost_http
import (
"context"
"net/http"
"net/url"
"time"
"github.com/aperturerobotics/controllerbus/bus"
"github.com/aperturerobotics/controllerbus/directive"
"github.com/pkg/errors"
)
// LookupHTTPHandler is a directive to lookup a HTTP handler.
type LookupHTTPHandler interface {
// Directive indicates LookupHTTPHandler is a directive.
directive.Directive
// LookupHTTPHandlerMethod is the method string for the request.
// Can be empty to allow any.
LookupHTTPHandlerMethod() string
// LookupHTTPHandlerURL is the URL for the request.
LookupHTTPHandlerURL() *url.URL
// LookupHTTPHandlerClientID is a string identifying the client.
// Can be empty.
LookupHTTPHandlerClientID() string
}
// LookupHTTPHandlerValue is the result type for LookupHTTPHandler.
// Multiple results may be pushed to the directive.
type LookupHTTPHandlerValue = http.Handler
// lookupHTTPHandler implements LookupHTTPHandler
type lookupHTTPHandler struct {
handlerMethod string
handlerURL *url.URL
clientID string
}
// NewLookupHTTPHandler constructs a new LookupHTTPHandler directive.
// handlerMethod can be empty to allow any.
func NewLookupHTTPHandler(handlerMethod string, handlerURL *url.URL, clientID string) LookupHTTPHandler {
return &lookupHTTPHandler{handlerMethod: handlerMethod, handlerURL: handlerURL, clientID: clientID}
}
// ExLookupHTTPHandlers executes the LookupHTTPHandler directive.
// If waitOne is set, waits for at least one value before returning.
// handlerMethod can be empty to allow any.
func ExLookupHTTPHandlers(
ctx context.Context,
b bus.Bus,
handlerMethod string,
handlerURL *url.URL,
clientID string,
waitOne bool,
) ([]LookupHTTPHandlerValue, directive.Instance, directive.Reference, error) {
return bus.ExecCollectValues[LookupHTTPHandlerValue](
ctx,
b,
NewLookupHTTPHandler(handlerMethod, handlerURL, clientID),
waitOne,
nil,
)
}
// ExLookupFirstHTTPHandler waits for the first HTTP handler to be returned.
// if returnIfIdle is set and the directive becomes idle, returns nil, nil, nil,
// handlerMethod can be empty to allow any.
func ExLookupFirstHTTPHandler(
ctx context.Context,
b bus.Bus,
handlerMethod string,
handlerURL *url.URL,
clientID string,
returnIfIdle bool,
valDisposeCb func(),
) (LookupHTTPHandlerValue, directive.Instance, directive.Reference, error) {
return bus.ExecWaitValue[LookupHTTPHandlerValue](
ctx,
b,
NewLookupHTTPHandler(handlerMethod, handlerURL, clientID),
bus.ReturnIfIdle(returnIfIdle),
valDisposeCb,
nil,
)
}
// MatchServeMuxPattern matches a LookupHTTPMethod against at ServeMux.
func MatchServeMuxPattern(mux *http.ServeMux, dir LookupHTTPHandler) (handler http.Handler, pattern string) {
method := dir.LookupHTTPHandlerMethod()
if method == "" {
method = "OPTIONS"
}
return mux.Handler(&http.Request{Method: method, URL: dir.LookupHTTPHandlerURL()})
}
// Validate validates the directive.
// This is a cursory validation to see if the values "look correct."
func (d *lookupHTTPHandler) Validate() error {
if d.handlerURL == nil {
return errors.New("handler url cannot be nil")
}
return nil
}
// GetValueLookupHTTPHandlerOptions returns options relating to value handling.
func (d *lookupHTTPHandler) GetValueOptions() directive.ValueOptions {
return directive.ValueOptions{
UnrefDisposeDur: time.Millisecond * 250,
UnrefDisposeEmptyImmediate: true,
}
}
// LookupHTTPHandlerMethod is the method string for the request.
// Can be empty.
func (d *lookupHTTPHandler) LookupHTTPHandlerMethod() string {
return d.handlerMethod
}
// LookupHTTPHandlerURL is the URL for the request.
// Cannot be empty.
func (d *lookupHTTPHandler) LookupHTTPHandlerURL() *url.URL {
return d.handlerURL
}
// LookupHTTPHandlerClientID returns the client id.
// Can be empty.
func (d *lookupHTTPHandler) LookupHTTPHandlerClientID() string {
return d.clientID
}
// IsEquivalent checks if the other directive is equivalent. If two
// directives are equivalent, and the new directive does not superceed the
// old, then the new directive will be merged (de-duplicated) into the old.
func (d *lookupHTTPHandler) IsEquivalent(other directive.Directive) bool {
od, ok := other.(LookupHTTPHandler)
if !ok {
return false
}
if d.LookupHTTPHandlerMethod() != od.LookupHTTPHandlerMethod() {
return false
}
if d.LookupHTTPHandlerURL().String() != od.LookupHTTPHandlerURL().String() {
return false
}
if d.LookupHTTPHandlerClientID() != od.LookupHTTPHandlerClientID() {
return false
}
return true
}
// Superceeds checks if the directive overrides another.
// The other directive will be canceled if superceded.
func (d *lookupHTTPHandler) Superceeds(other directive.Directive) bool {
return false
}
// GetName returns the directive's type name.
// This is not necessarily unique, and is primarily intended for display.
func (d *lookupHTTPHandler) GetName() string {
return "LookupHTTPHandler"
}
// GetDebugString returns the directive arguments stringified.
// This should be something like param1="test", param2="test".
// This is not necessarily unique, and is primarily intended for display.
func (d *lookupHTTPHandler) GetDebugVals() directive.DebugValues {
vals := directive.DebugValues{}
if method := d.LookupHTTPHandlerMethod(); method != "" {
vals["method"] = []string{method}
}
vals["url"] = []string{d.LookupHTTPHandlerURL().String()}
if clientID := d.LookupHTTPHandlerClientID(); clientID != "" {
vals["client-id"] = []string{clientID}
}
return vals
}
// _ is a type assertion
var _ LookupHTTPHandler = ((*lookupHTTPHandler)(nil))