package proxy import ( "io" "net/http" "net/http/httptest" "net/url" "sync/atomic" "testing" ) func TestRemoteHostSharesHTTPTransport(t *testing.T) { h1, err := NewRemoteHost[struct{}]("10.0.0.1", "8080") if err != nil { t.Fatal(err) } h2, err := NewRemoteHost[struct{}]("10.0.0.2", "8080") if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = h1.Close() _ = h2.Close() }) if h1.client.Transport != h2.client.Transport { t.Fatal("expected all RemoteHost instances to share one http.Transport") } } func TestRemoteHostProxyUsesKeepAlive(t *testing.T) { var requests atomic.Int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requests.Add(1) w.WriteHeader(http.StatusOK) _, _ = io.WriteString(w, `{"ok":true}`) })) t.Cleanup(srv.Close) host, port, err := splitHostPort(srv.URL) if err != nil { t.Fatal(err) } remote, err := NewRemoteHost[struct{}](host, port) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = remote.Close() }) for range 3 { mw := NewMockResponseWriter() req, err := http.NewRequest(http.MethodGet, "/cart/1", nil) if err != nil { t.Fatal(err) } ok, err := remote.Proxy(1, mw, req, nil) if err != nil || !ok { t.Fatalf("Proxy failed: ok=%v err=%v status=%d body=%q", ok, err, mw.StatusCode, mw.Body.String()) } } if requests.Load() != 3 { t.Fatalf("server requests = %d, want 3", requests.Load()) } } func TestRemoteHostCloseDoesNotBreakSharedTransport(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })) t.Cleanup(srv.Close) host, port, err := splitHostPort(srv.URL) if err != nil { t.Fatal(err) } h1, err := NewRemoteHost[struct{}](host, port) if err != nil { t.Fatal(err) } h2, err := NewRemoteHost[struct{}](host, port) if err != nil { t.Fatal(err) } if err := h1.Close(); err != nil { t.Fatal(err) } mw := NewMockResponseWriter() req, err := http.NewRequest(http.MethodGet, "/health", nil) if err != nil { t.Fatal(err) } ok, err := h2.Proxy(0, mw, req, nil) if err != nil || !ok || mw.StatusCode != http.StatusOK { t.Fatalf("second host proxy after first close failed: ok=%v err=%v status=%d", ok, err, mw.StatusCode) } } func splitHostPort(rawURL string) (host, port string, err error) { u, err := url.Parse(rawURL) if err != nil { return "", "", err } return u.Hostname(), u.Port(), nil }