@marcel91200 / caddy Mirror · read-only / commits / dc4d1473
Fork 0

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