Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 13, 20:30 UTC
reverseproxy: Expand SRV/A addrs for cache key
Hopefully fix #4645
Matthew Holt committed
Mar 18, 2022 at 13:42 UTC
dc4d147388547515f77447d594024386b732e7d4
1 file changed
+39
-19
modules/caddyhttp/reverseproxy/upstreams.go
+39
-19
@@ -72,11 +72,6 @@ func (SRVUpstreams) CaddyModule() caddy.ModuleInfo {
72
}
73
}
74
75
-// String returns the RFC 2782 representation of the SRV domain.
76
-func (su SRVUpstreams) String() string {
77
- return fmt.Sprintf("_%s._%s.%s", su.Service, su.Proto, su.Name)
78
-}
79
-
75
func (su *SRVUpstreams) Provision(ctx caddy.Context) error {
76
su.logger = ctx.Logger(su)
77
if su.Refresh == 0 {
@@ -109,11 +104,11 @@ func (su *SRVUpstreams) Provision(ctx caddy.Context) error {
104
}
105
106
func (su SRVUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
112
- suStr := su.String()
107
+ suAddr, service, proto, name := su.expandedAddr(r)
108
109
// first, use a cheap read-lock to return a cached result quickly
110
srvsMu.RLock()
116
- cached := srvs[suStr]
111
+ cached := srvs[suAddr]
112
srvsMu.RUnlock()
113
if cached.isFresh() {
114
return cached.upstreams, nil
@@ -126,17 +121,11 @@ func (su SRVUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
121
// check to see if it's still stale, since we're now in a different
122
// lock from when we first checked freshness; another goroutine might
123
// have refreshed it in the meantime before we re-obtained our lock
129
- cached = srvs[suStr]
124
+ cached = srvs[suAddr]
125
if cached.isFresh() {
126
return cached.upstreams, nil
127
}
128
134
- // prepare parameters and perform the SRV lookup
135
- repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
136
- service := repl.ReplaceAll(su.Service, "")
137
- proto := repl.ReplaceAll(su.Proto, "")
138
- name := repl.ReplaceAll(su.Name, "")
139
-
129
su.logger.Debug("refreshing SRV upstreams",
130
zap.String("service", service),
131
zap.String("proto", proto),
@@ -172,7 +161,7 @@ func (su SRVUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
161
}
162
}
163
175
- srvs[suStr] = srvLookup{
164
+ srvs[suAddr] = srvLookup{
165
srvUpstreams: su,
166
freshness: time.Now(),
167
upstreams: upstreams,
@@ -181,6 +170,37 @@ func (su SRVUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
170
return upstreams, nil
171
}
172
173
+func (su SRVUpstreams) String() string {
174
+ if su.Service == "" && su.Proto == "" {
175
+ return su.Name
176
+ }
177
+ return su.formattedAddr(su.Service, su.Proto, su.Name)
178
+}
179
+
180
+// expandedAddr expands placeholders in the configured SRV domain labels.
181
+// The return values are: addr, the RFC 2782 representation of the SRV domain;
182
+// service, the service; proto, the protocol; and name, the name.
183
+// If su.Service and su.Proto are empty, name will be returned as addr instead.
184
+func (su SRVUpstreams) expandedAddr(r *http.Request) (addr, service, proto, name string) {
185
+ repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
186
+ name = repl.ReplaceAll(su.Name, "")
187
+ if su.Service == "" && su.Proto == "" {
188
+ addr = name
189
+ name = ""
190
+ return
191
+ }
192
+ service = repl.ReplaceAll(su.Service, "")
193
+ proto = repl.ReplaceAll(su.Proto, "")
194
+ addr = su.formattedAddr(service, proto, name)
195
+ return
196
+}
197
+
198
+// formattedAddr the RFC 2782 representation of the SRV domain, in
199
+// the form "_service._proto.name".
200
+func (SRVUpstreams) formattedAddr(service, proto, name string) string {
201
+ return fmt.Sprintf("_%s._%s.%s", service, proto, name)
202
+}
203
+
204
type srvLookup struct {
205
srvUpstreams SRVUpstreams
206
freshness time.Time
@@ -234,8 +254,6 @@ func (AUpstreams) CaddyModule() caddy.ModuleInfo {
254
}
255
}
256
237
-func (au AUpstreams) String() string { return au.Name }
238
-
257
func (au *AUpstreams) Provision(_ caddy.Context) error {
258
if au.Refresh == 0 {
259
au.Refresh = caddy.Duration(time.Minute)
@@ -270,7 +288,8 @@ func (au *AUpstreams) Provision(_ caddy.Context) error {
288
}
289
290
func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
273
- auStr := au.String()
291
+ repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
292
+ auStr := repl.ReplaceAll(au.String(), "")
293
294
// first, use a cheap read-lock to return a cached result quickly
295
aAaaaMu.RLock()
@@ -292,7 +311,6 @@ func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
311
return cached.upstreams, nil
312
}
313
295
- repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
314
name := repl.ReplaceAll(au.Name, "")
315
port := repl.ReplaceAll(au.Port, "")
316
@@ -325,6 +343,8 @@ func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
343
return upstreams, nil
344
}
345
346
+func (au AUpstreams) String() string { return au.Name }
347
+
348
type aLookup struct {
349
aUpstreams AUpstreams
350
freshness time.Time