summaryrefslogtreecommitdiffhomepage
path: root/modules
diff options
context:
space:
mode:
authorJesper Brix Rosenkilde <[email protected]>2024-08-19 18:55:55 +0200
committerGitHub <[email protected]>2024-08-19 10:55:55 -0600
commit54a0c8f94821f393edec1a1bc9459f2363c95117 (patch)
tree2b00fcec797f6cc05680300346a2154d9fa0ab05 /modules
parent043fe41ab8d39615f346b63c1e51bcf16feda1d8 (diff)
downloadcaddy-54a0c8f94821f393edec1a1bc9459f2363c95117.tar.gz
caddy-54a0c8f94821f393edec1a1bc9459f2363c95117.zip
reverseproxy: Active health checks request body option (#6520)
* Add an option to specify the body used for active health checks * Replacer on request body
Diffstat (limited to 'modules')
-rw-r--r--modules/caddyhttp/reverseproxy/caddyfile.go31
-rw-r--r--modules/caddyhttp/reverseproxy/healthchecks.go19
2 files changed, 38 insertions, 12 deletions
diff --git a/modules/caddyhttp/reverseproxy/caddyfile.go b/modules/caddyhttp/reverseproxy/caddyfile.go
index 4ca5d0e0d..cd0e5d949 100644
--- a/modules/caddyhttp/reverseproxy/caddyfile.go
+++ b/modules/caddyhttp/reverseproxy/caddyfile.go
@@ -69,19 +69,20 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
// lb_retry_match <request-matcher>
//
// # active health checking
-// health_uri <uri>
-// health_port <port>
-// health_interval <interval>
-// health_passes <num>
-// health_fails <num>
-// health_timeout <duration>
-// health_status <status>
-// health_body <regexp>
+// health_uri <uri>
+// health_port <port>
+// health_interval <interval>
+// health_passes <num>
+// health_fails <num>
+// health_timeout <duration>
+// health_status <status>
+// health_body <regexp>
+// health_method <value>
+// health_request_body <value>
// health_follow_redirects
// health_headers {
// <field> [<values...>]
// }
-// health_method <value>
//
// # passive health checking
// fail_duration <duration>
@@ -425,6 +426,18 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
}
h.HealthChecks.Active.Method = d.Val()
+ case "health_request_body":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ if h.HealthChecks == nil {
+ h.HealthChecks = new(HealthChecks)
+ }
+ if h.HealthChecks.Active == nil {
+ h.HealthChecks.Active = new(ActiveHealthChecks)
+ }
+ h.HealthChecks.Active.Body = d.Val()
+
case "health_interval":
if !d.NextArg() {
return d.ArgErr()
diff --git a/modules/caddyhttp/reverseproxy/healthchecks.go b/modules/caddyhttp/reverseproxy/healthchecks.go
index 3b5a6a3af..efa1dbf09 100644
--- a/modules/caddyhttp/reverseproxy/healthchecks.go
+++ b/modules/caddyhttp/reverseproxy/healthchecks.go
@@ -24,6 +24,7 @@ import (
"regexp"
"runtime/debug"
"strconv"
+ "strings"
"time"
"go.uber.org/zap"
@@ -93,6 +94,9 @@ type ActiveHealthChecks struct {
// The HTTP method to use for health checks (default "GET").
Method string `json:"method,omitempty"`
+ // The body to send with the health check request.
+ Body string `json:"body,omitempty"`
+
// Whether to follow HTTP redirects in response to active health checks (default off).
FollowRedirects bool `json:"follow_redirects,omitempty"`
@@ -396,6 +400,16 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ
u.Path = h.HealthChecks.Active.Path
}
+ // replacer used for both body and headers. Only globals (env vars, system info, etc.) are available
+ repl := caddy.NewReplacer()
+
+ // if body is provided, create a reader for it, otherwise nil
+ var requestBody io.Reader
+ if h.HealthChecks.Active.Body != "" {
+ // set body, using replacer
+ requestBody = strings.NewReader(repl.ReplaceAll(h.HealthChecks.Active.Body, ""))
+ }
+
// attach dialing information to this request, as well as context values that
// may be expected by handlers of this request
ctx := h.ctx.Context
@@ -403,15 +417,14 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ
ctx = context.WithValue(ctx, caddyhttp.VarsCtxKey, map[string]any{
dialInfoVarKey: dialInfo,
})
- req, err := http.NewRequestWithContext(ctx, h.HealthChecks.Active.Method, u.String(), nil)
+ req, err := http.NewRequestWithContext(ctx, h.HealthChecks.Active.Method, u.String(), requestBody)
if err != nil {
return fmt.Errorf("making request: %v", err)
}
ctx = context.WithValue(ctx, caddyhttp.OriginalRequestCtxKey, *req)
req = req.WithContext(ctx)
- // set headers, using a replacer with only globals (env vars, system info, etc.)
- repl := caddy.NewReplacer()
+ // set headers, using replacer
repl.Set("http.reverse_proxy.active.target_upstream", networkAddr)
for key, vals := range h.HealthChecks.Active.Headers {
key = repl.ReplaceAll(key, "")