Repository: caddyserver/caddy
File: modules/caddyhttp/reverseproxy/healthchecks.go (Go)

Code before:
			}
		}
	}

	// if we have a provisioned uri, use that, otherwise use
	// the deprecated Path option
	if h.HealthChecks.Active.uri != nil {
		u.Path = h.HealthChecks.Active.uri.Path
		u.RawQuery = h.HealthChecks.Active.uri.RawQuery
	} else {
		u.Path = h.HealthChecks.Active.Path
	}

	// attach dialing information to this request, as well as context values that
	// may be expected by handlers of this request
	ctx := h.ctx.Context
	ctx = context.WithValue(ctx, caddy.ReplacerCtxKey, caddy.NewReplacer())
	ctx = context.WithValue(ctx, caddyhttp.VarsCtxKey, map[string]any{
		dialInfoVarKey: dialInfo,
	})
	req, err := http.NewRequestWithContext(ctx, h.HealthChecks.Active.Method, u.String(), nil)
	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()
	repl.Set("http.reverse_proxy.active.target_upstream", networkAddr)
	for key, vals := range h.HealthChecks.Active.Headers {
		key = repl.ReplaceAll(key, "")
		if key == "Host" {
			req.Host = repl.ReplaceAll(h.HealthChecks.Active.Headers.Get(key), "")
			continue
		}
		for _, val := range vals {
			req.Header.Add(key, repl.ReplaceKnown(val, ""))
		}
	}

	markUnhealthy := func() {
		// increment failures and then check if it has reached the threshold to mark unhealthy
		err := upstream.Host.countHealthFail(1)
		if err != nil {
			h.HealthChecks.Active.logger.Error("could not count active health failure",
				zap.String("host", upstream.Dial),
				zap.Error(err))
			return
		}
		if upstream.Host.activeHealthFails() >= h.HealthChecks.Active.Fails {

Review comment (suggestion):
If `Method` is not set by the user, the value here will be empty string.

Code after:
		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 {
		u.Path = h.HealthChecks.Active.uri.Path
		u.RawQuery = h.HealthChecks.Active.uri.RawQuery
	} else {
		u.Path = h.HealthChecks.Active.Path
	}

	// attach dialing information to this request, as well as context values that
	// may be expected by handlers of this request
	ctx := h.ctx.Context
	ctx = context.WithValue(ctx, caddy.ReplacerCtxKey, caddy.NewReplacer())
	ctx = context.WithValue(ctx, caddyhttp.VarsCtxKey, map[string]any{
		dialInfoVarKey: dialInfo,
	})
	req, err := http.NewRequestWithContext(ctx, h.HealthChecks.Active.Method, u.String(), nil)
	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()
	repl.Set("http.reverse_proxy.active.target_upstream", networkAddr)
	for key, vals := range h.HealthChecks.Active.Headers {
		key = repl.ReplaceAll(key, "")
		if key == "Host" {
			req.Host = repl.ReplaceAll(h.HealthChecks.Active.Headers.Get(key), "")
			continue
		}
		for _, val := range vals {
			req.Header.Add(key, repl.ReplaceKnown(val, ""))
		}
	}

	markUnhealthy := func() {
		// increment failures and then check if it has reached the threshold to mark unhealthy
		err := upstream.Host.countHealthFail(1)
		if err != nil {
			h.HealthChecks.Active.logger.Error("could not count active health failure",