From 4636109ce17e6ba5f46e73b7b1f3ae82d076a625 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Mon, 10 Apr 2023 16:08:40 -0400 Subject: reverseproxy: Remove deprecated `lookup_srv` (#5396) --- modules/caddyhttp/reverseproxy/healthchecks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/caddyhttp/reverseproxy/healthchecks.go') diff --git a/modules/caddyhttp/reverseproxy/healthchecks.go b/modules/caddyhttp/reverseproxy/healthchecks.go index c27b24f..cfc7bdf 100644 --- a/modules/caddyhttp/reverseproxy/healthchecks.go +++ b/modules/caddyhttp/reverseproxy/healthchecks.go @@ -203,7 +203,7 @@ func (h *Handler) doActiveHealthCheckForAllHosts() { } addr.StartPort, addr.EndPort = hcp, hcp } - if upstream.LookupSRV == "" && addr.PortRangeSize() != 1 { + if addr.PortRangeSize() != 1 { h.HealthChecks.Active.logger.Error("multiple addresses (upstream must map to only one address)", zap.String("address", networkAddr), ) -- cgit v1.2.3 From 335cd2e8a4f2a91cb2c55a6c2e624a4c4ccddb0c Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Fri, 5 May 2023 17:19:22 -0400 Subject: reverseproxy: Fix active health check header canonicalization, refactor (#5446) --- modules/caddyhttp/reverseproxy/healthchecks.go | 73 +++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) (limited to 'modules/caddyhttp/reverseproxy/healthchecks.go') diff --git a/modules/caddyhttp/reverseproxy/healthchecks.go b/modules/caddyhttp/reverseproxy/healthchecks.go index cfc7bdf..c969c8c 100644 --- a/modules/caddyhttp/reverseproxy/healthchecks.go +++ b/modules/caddyhttp/reverseproxy/healthchecks.go @@ -24,7 +24,6 @@ import ( "regexp" "runtime/debug" "strconv" - "strings" "time" "github.com/caddyserver/caddy/v2" @@ -106,6 +105,76 @@ type ActiveHealthChecks struct { logger *zap.Logger } +// Provision ensures that a is set up properly before use. +func (a *ActiveHealthChecks) Provision(ctx caddy.Context, h *Handler) error { + if !a.IsEnabled() { + return nil + } + + // Canonicalize the header keys ahead of time, since + // JSON unmarshaled headers may be incorrect + cleaned := http.Header{} + for key, hdrs := range a.Headers { + for _, val := range hdrs { + cleaned.Add(key, val) + } + } + a.Headers = cleaned + + h.HealthChecks.Active.logger = h.logger.Named("health_checker.active") + + timeout := time.Duration(a.Timeout) + if timeout == 0 { + timeout = 5 * time.Second + } + + if a.Path != "" { + a.logger.Warn("the 'path' option is deprecated, please use 'uri' instead!") + } + + // parse the URI string (supports path and query) + if a.URI != "" { + parsedURI, err := url.Parse(a.URI) + if err != nil { + return err + } + a.uri = parsedURI + } + + a.httpClient = &http.Client{ + Timeout: timeout, + Transport: h.Transport, + } + + for _, upstream := range h.Upstreams { + // if there's an alternative port for health-check provided in the config, + // then use it, otherwise use the port of upstream. + if a.Port != 0 { + upstream.activeHealthCheckPort = a.Port + } + } + + if a.Interval == 0 { + a.Interval = caddy.Duration(30 * time.Second) + } + + if a.ExpectBody != "" { + var err error + a.bodyRegexp, err = regexp.Compile(a.ExpectBody) + if err != nil { + return fmt.Errorf("expect_body: compiling regular expression: %v", err) + } + } + + return nil +} + +// IsEnabled checks if the active health checks have +// the minimum config necessary to be enabled. +func (a *ActiveHealthChecks) IsEnabled() bool { + return a.Path != "" || a.URI != "" || a.Port != 0 +} + // PassiveHealthChecks holds configuration related to passive // health checks (that is, health checks which occur during // the normal flow of request proxying). @@ -280,7 +349,7 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, upstre ctx = context.WithValue(ctx, caddyhttp.OriginalRequestCtxKey, *req) req = req.WithContext(ctx) for key, hdrs := range h.HealthChecks.Active.Headers { - if strings.ToLower(key) == "host" { + if key == "Host" { req.Host = h.HealthChecks.Active.Headers.Get(key) } else { req.Header[key] = hdrs -- cgit v1.2.3 From 7a69ae757197660d26095045fba385c613926d77 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Thu, 22 Jun 2023 18:20:30 -0400 Subject: reverseproxy: Honor `tls_except_port` for active health checks (#5591) --- modules/caddyhttp/reverseproxy/healthchecks.go | 41 ++++++++++++++++---------- 1 file changed, 25 insertions(+), 16 deletions(-) (limited to 'modules/caddyhttp/reverseproxy/healthchecks.go') diff --git a/modules/caddyhttp/reverseproxy/healthchecks.go b/modules/caddyhttp/reverseproxy/healthchecks.go index c969c8c..80b635a 100644 --- a/modules/caddyhttp/reverseproxy/healthchecks.go +++ b/modules/caddyhttp/reverseproxy/healthchecks.go @@ -306,16 +306,35 @@ func (h *Handler) doActiveHealthCheckForAllHosts() { // the host's health status fails. func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, upstream *Upstream) error { // create the URL for the request that acts as a health check - scheme := "http" - if ht, ok := h.Transport.(TLSTransport); ok && ht.TLSEnabled() { - // this is kind of a hacky way to know if we should use HTTPS, but whatever - scheme = "https" - } u := &url.URL{ - Scheme: scheme, + Scheme: "http", Host: hostAddr, } + // split the host and port if possible, override the port if configured + host, port, err := net.SplitHostPort(hostAddr) + if err != nil { + host = hostAddr + } + if h.HealthChecks.Active.Port != 0 { + port := strconv.Itoa(h.HealthChecks.Active.Port) + u.Host = net.JoinHostPort(host, port) + } + + // this is kind of a hacky way to know if we should use HTTPS, but whatever + if tt, ok := h.Transport.(TLSTransport); ok && tt.TLSEnabled() { + u.Scheme = "https" + + // if the port is in the except list, flip back to HTTP + if ht, ok := h.Transport.(*HTTPTransport); ok { + for _, exceptPort := range ht.TLS.ExceptPorts { + if exceptPort == port { + u.Scheme = "http" + } + } + } + } + // if we have a provisioned uri, use that, otherwise use // the deprecated Path option if h.HealthChecks.Active.uri != nil { @@ -325,16 +344,6 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, upstre u.Path = h.HealthChecks.Active.Path } - // adjust the port, if configured to be different - if h.HealthChecks.Active.Port != 0 { - portStr := strconv.Itoa(h.HealthChecks.Active.Port) - host, _, err := net.SplitHostPort(hostAddr) - if err != nil { - host = hostAddr - } - u.Host = net.JoinHostPort(host, portStr) - } - // attach dialing information to this request, as well as context values that // may be expected by handlers of this request ctx := h.ctx.Context -- cgit v1.2.3 From d6f86cccf5fa5b4eb30141da390cf2439746c5da Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Mon, 14 Aug 2023 23:41:15 +0800 Subject: ci: use gci linter (#5708) * use gofmput to format code * use gci to format imports * reconfigure gci * linter autofixes * rearrange imports a little * export GOOS=windows golangci-lint run ./... --fix --- modules/caddyhttp/reverseproxy/healthchecks.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'modules/caddyhttp/reverseproxy/healthchecks.go') diff --git a/modules/caddyhttp/reverseproxy/healthchecks.go b/modules/caddyhttp/reverseproxy/healthchecks.go index 80b635a..1b4f2d0 100644 --- a/modules/caddyhttp/reverseproxy/healthchecks.go +++ b/modules/caddyhttp/reverseproxy/healthchecks.go @@ -26,9 +26,10 @@ import ( "strconv" "time" + "go.uber.org/zap" + "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/modules/caddyhttp" - "go.uber.org/zap" ) // HealthChecks configures active and passive health checks. -- cgit v1.2.3 From 05dbe1c171846b0b683dedbe2c4c20683e867ba0 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Wed, 11 Oct 2023 11:50:28 -0400 Subject: reverseproxy: Replace health header placeholders (#5861) --- modules/caddyhttp/reverseproxy/healthchecks.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'modules/caddyhttp/reverseproxy/healthchecks.go') diff --git a/modules/caddyhttp/reverseproxy/healthchecks.go b/modules/caddyhttp/reverseproxy/healthchecks.go index 1b4f2d0..ad21ccb 100644 --- a/modules/caddyhttp/reverseproxy/healthchecks.go +++ b/modules/caddyhttp/reverseproxy/healthchecks.go @@ -358,11 +358,17 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, upstre } ctx = context.WithValue(ctx, caddyhttp.OriginalRequestCtxKey, *req) req = req.WithContext(ctx) - for key, hdrs := range h.HealthChecks.Active.Headers { + + // set headers, using a replacer with only globals (env vars, system info, etc.) + repl := caddy.NewReplacer() + for key, vals := range h.HealthChecks.Active.Headers { + key = repl.ReplaceAll(key, "") if key == "Host" { - req.Host = h.HealthChecks.Active.Headers.Get(key) - } else { - req.Header[key] = hdrs + req.Host = repl.ReplaceAll(h.HealthChecks.Active.Headers.Get(key), "") + continue + } + for _, val := range vals { + req.Header.Add(key, repl.ReplaceKnown(val, "")) } } -- cgit v1.2.3