From ebfc72c14fc9be7bc1516817cad5bf0a844af55c Mon Sep 17 00:00:00 2001 From: team-humaki Date: Sun, 13 Sep 2026 20:31:25 -0700 Subject: [PATCH] client: copy TLS state onto DialContext response Fixes #996 --- client.go | 20 ++++++++++++++++++++ client_server_test.go | 13 +++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/client.go b/client.go index 00917ea3..2d016f86 100644 --- a/client.go +++ b/client.go @@ -350,6 +350,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } return nil, nil, err } + setResponseTLS(resp, netConn) if d.Jar != nil { if rc := resp.Cookies(); len(rc) > 0 { @@ -504,6 +505,25 @@ func cloneTLSConfig(cfg *tls.Config) *tls.Config { return cfg.Clone() } +// connectionStater is implemented by tls.Conn and custom TLS wrappers. +type connectionStater interface { + ConnectionState() tls.ConnectionState +} + +// setResponseTLS copies the TLS connection state onto resp, matching net/http +// Transport so callers can inspect resp.TLS after DialContext on a wss URL. +func setResponseTLS(resp *http.Response, conn net.Conn) { + if resp == nil { + return + } + cs, ok := conn.(connectionStater) + if !ok { + return + } + state := cs.ConnectionState() + resp.TLS = &state +} + func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error { if err := tlsConn.HandshakeContext(ctx); err != nil { return err diff --git a/client_server_test.go b/client_server_test.go index e4546aea..edf41066 100644 --- a/client_server_test.go +++ b/client_server_test.go @@ -246,11 +246,14 @@ func TestDial(t *testing.T) { s := newServer(t) defer s.Close() - ws, _, err := cstDialer.Dial(s.URL, nil) + ws, resp, err := cstDialer.Dial(s.URL, nil) if err != nil { t.Fatalf("Dial: %v", err) } defer ws.Close() + if resp != nil && resp.TLS != nil { + t.Fatalf("Dial: resp.TLS = %+v, want nil on ws URL", resp.TLS) + } sendRecv(t, ws) } @@ -322,11 +325,17 @@ func TestDialTLS(t *testing.T) { d := cstDialer d.TLSClientConfig = &tls.Config{RootCAs: rootCAs(t, s.Server)} - ws, _, err := d.Dial(s.URL, nil) + ws, resp, err := d.Dial(s.URL, nil) if err != nil { t.Fatalf("Dial: %v", err) } defer ws.Close() + if resp == nil || resp.TLS == nil { + t.Fatalf("Dial TLS response: resp.TLS = nil, want connection state") + } + if !resp.TLS.HandshakeComplete { + t.Fatalf("Dial TLS response: HandshakeComplete = false") + } sendRecv(t, ws) }