@marcel91200 / caddy Mirror · read-only / commits / 091add5a
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 11, 14:45 UTC

caddytest: make TestReverseProxyHealthCheck deterministic with poll instead of sleep (#7474)

Start lightweight backend servers before starting Caddy so active health checks probe a ready backend instead of the same Caddy instance during provisioning. This removes the startup race without fixed sleeps or polling.

Amirhf committed Feb 17, 2026 at 15:11 UTC 091add5ae3dc0ab3265e45b4417fc06fb8a05a39
1 file changed +35 -9
caddytest/integration/reverseproxy_test.go
+35 -9
@@ -8,7 +8,6 @@ import (
8 "runtime"
9 "strings"
10 "testing"
11 - "time"
11
12 "github.com/caddyserver/caddy/v2/caddytest"
13 )
@@ -327,6 +326,41 @@ func TestReverseProxyWithPlaceholderTCPDialAddress(t *testing.T) {
326 }
327
328 func TestReverseProxyHealthCheck(t *testing.T) {
329 + // Start lightweight backend servers so they're ready before Caddy's
330 + // active health checker runs; this avoids a startup race where the
331 + // health checker probes backends that haven't yet begun accepting
332 + // connections and marks them unhealthy.
333 + //
334 + // This mirrors how health checks are typically used in practice (to a separate
335 + // backend service) and avoids probing the same Caddy instance while it's still
336 + // provisioning and not ready to accept connections.
337 +
338 + // backend server that responds to proxied requests
339 + helloSrv := &http.Server{
340 + Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
341 + _, _ = w.Write([]byte("Hello, World!"))
342 + }),
343 + }
344 + ln0, err := net.Listen("tcp", "127.0.0.1:2020")
345 + if err != nil {
346 + t.Fatalf("failed to listen on 127.0.0.1:2020: %v", err)
347 + }
348 + go helloSrv.Serve(ln0)
349 + t.Cleanup(func() { helloSrv.Close(); ln0.Close() })
350 +
351 + // backend server that serves health checks
352 + healthSrv := &http.Server{
353 + Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
354 + _, _ = w.Write([]byte("ok"))
355 + }),
356 + }
357 + ln1, err := net.Listen("tcp", "127.0.0.1:2021")
358 + if err != nil {
359 + t.Fatalf("failed to listen on 127.0.0.1:2021: %v", err)
360 + }
361 + go healthSrv.Serve(ln1)
362 + t.Cleanup(func() { healthSrv.Close(); ln1.Close() })
363 +
364 tester := caddytest.NewTester(t)
365 tester.InitServer(`
366 {
@@ -336,12 +370,6 @@ func TestReverseProxyHealthCheck(t *testing.T) {
370 https_port 9443
371 grace_period 1ns
372 }
339 - http://localhost:2020 {
340 - respond "Hello, World!"
341 - }
342 - http://localhost:2021 {
343 - respond "ok"
344 - }
373 http://localhost:9080 {
374 reverse_proxy {
375 to localhost:2020
@@ -355,8 +383,6 @@ func TestReverseProxyHealthCheck(t *testing.T) {
383 }
384 }
385 `, "caddyfile")
358 -
359 - time.Sleep(100 * time.Millisecond) // TODO: for some reason this test seems particularly flaky, getting 503 when it should be 200, unless we wait
386 tester.AssertGetResponse("http://localhost:9080/", 200, "Hello, World!")
387 }
388