diff --git a/codersdk/client.go b/codersdk/client.go index b0fb4d9764b3c..2097225ff489c 100644 --- a/codersdk/client.go +++ b/codersdk/client.go @@ -354,7 +354,7 @@ func (c *Client) Dial(ctx context.Context, path string, opts *websocket.DialOpti if opts.HTTPHeader == nil { opts.HTTPHeader = http.Header{} } - if opts.HTTPHeader.Get("tokenHeader") == "" { + if opts.HTTPHeader.Get(tokenHeader) == "" { opts.HTTPHeader.Set(tokenHeader, c.SessionToken()) } diff --git a/vpn/client.go b/vpn/client.go index e3f3e767fc477..d52718e7fa7ab 100644 --- a/vpn/client.go +++ b/vpn/client.go @@ -92,7 +92,7 @@ func (*client) NewConn(initCtx context.Context, serverURL *url.URL, token string sdk.SetSessionToken(token) sdk.HTTPClient.Transport = &codersdk.HeaderTransport{ Transport: http.DefaultTransport, - Header: headers, + Header: headers.Clone(), } // New context, separate from initCtx. We don't want to cancel the @@ -129,17 +129,18 @@ func (*client) NewConn(initCtx context.Context, serverURL *url.URL, token string headers.Set(codersdk.SessionTokenHeader, token) dialer := workspacesdk.NewWebsocketDialer(options.Logger, rpcURL, &websocket.DialOptions{ HTTPClient: sdk.HTTPClient, - HTTPHeader: headers, + HTTPHeader: headers.Clone(), CompressionMode: websocket.CompressionDisabled, }, workspacesdk.WithWorkspaceUpdates(&proto.WorkspaceUpdatesRequest{ WorkspaceOwnerId: tailnet.UUIDToByteSlice(me.ID), })) + clonedHeaders := headers.Clone() ip := tailnet.CoderServicePrefix.RandomAddr() conn, err := tailnet.NewConn(&tailnet.Options{ Addresses: []netip.Prefix{netip.PrefixFrom(ip, 128)}, DERPMap: connInfo.DERPMap, - DERPHeader: &headers, + DERPHeader: &clonedHeaders, DERPForceWebSockets: connInfo.DERPForceWebSockets, Logger: options.Logger, BlockEndpoints: connInfo.DisableDirectConnections, diff --git a/vpn/client_test.go b/vpn/client_test.go index 4b05bf108e8e4..de13b2349d5d4 100644 --- a/vpn/client_test.go +++ b/vpn/client_test.go @@ -90,6 +90,8 @@ func TestClient_WorkspaceUpdates(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/api/v2/users/me": + values := r.Header.Values(codersdk.SessionTokenHeader) + assert.Len(t, values, 1, "expected exactly one session token header value") httpapi.Write(ctx, w, http.StatusOK, codersdk.User{ ReducedUser: codersdk.ReducedUser{ MinimalUser: codersdk.MinimalUser{ @@ -101,6 +103,8 @@ func TestClient_WorkspaceUpdates(t *testing.T) { user <- struct{}{} case "/api/v2/workspaceagents/connection": + values := r.Header.Values(codersdk.SessionTokenHeader) + assert.Len(t, values, 1, "expected exactly one session token header value") httpapi.Write(ctx, w, http.StatusOK, tc.agentConnectionInfo) connInfo <- struct{}{} @@ -109,6 +113,9 @@ func TestClient_WorkspaceUpdates(t *testing.T) { cVer := r.URL.Query().Get("version") assert.Equal(t, "2.3", cVer) + values := r.Header.Values(codersdk.SessionTokenHeader) + assert.Len(t, values, 1, "expected exactly one session token header value") + sws, err := websocket.Accept(w, r, nil) if !assert.NoError(t, err) { return