From 70389435c37b208ff24736bc058e8ece7ed5ae14 Mon Sep 17 00:00:00 2001 From: Jeff Haynie Date: Sat, 2 May 2026 13:38:41 -0500 Subject: [PATCH] fix(gravity): identify health probes --- gravity/grpc_client.go | 6 ++++++ gravity/health_probe_test.go | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 gravity/health_probe_test.go diff --git a/gravity/grpc_client.go b/gravity/grpc_client.go index ca2df5e..d4b647f 100644 --- a/gravity/grpc_client.go +++ b/gravity/grpc_client.go @@ -92,6 +92,11 @@ const ( // ipv6 destination" → RST, breaking HTTP/2 connection reuse and // long-lived connections. DefaultBindingTTL = 10 * time.Minute + + // GravityHealthProbeUserAgent identifies hadron/gravity-client HTTP + // readiness probes to ion. Ion uses this to answer control-plane + // readiness without admitting public traffic during tableflip. + GravityHealthProbeUserAgent = "Agentuity-Gravity-HealthProbe/1.0" ) // TunnelKeepaliveMarker is a 4-byte magic prefix for tunnel keepalive packets. @@ -4539,6 +4544,7 @@ func (g *GravityClient) doHealthProbe(probeURL string) (int, error) { if err != nil { return 0, err } + req.Header.Set("User-Agent", GravityHealthProbeUserAgent) resp, err := http.DefaultClient.Do(req) if err != nil { return 0, err diff --git a/gravity/health_probe_test.go b/gravity/health_probe_test.go new file mode 100644 index 0000000..7d0f421 --- /dev/null +++ b/gravity/health_probe_test.go @@ -0,0 +1,39 @@ +package gravity + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/agentuity/go-common/logger" +) + +func TestDoHealthProbeSetsGravityUserAgent(t *testing.T) { + t.Parallel() + + var gotUserAgent string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + gotUserAgent = r.Header.Get("User-Agent") + w.WriteHeader(http.StatusOK) + })) + defer srv.Close() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + g := &GravityClient{ + context: ctx, + logger: logger.NewTestLogger(), + } + + status, err := g.doHealthProbe(srv.URL) + if err != nil { + t.Fatalf("doHealthProbe returned error: %v", err) + } + if status != http.StatusOK { + t.Fatalf("expected status %d, got %d", http.StatusOK, status) + } + if gotUserAgent != GravityHealthProbeUserAgent { + t.Fatalf("expected User-Agent %q, got %q", GravityHealthProbeUserAgent, gotUserAgent) + } +}