@@ -1371,6 +1371,47 @@ func TestTransportDialPreservesNetOpProxyError(t *testing.T) {
1371
1371
}
1372
1372
}
1373
1373
1374
+ // Issue 36431: calls to RoundTrip should not mutate t.ProxyConnectHeader.
1375
+ //
1376
+ // (A bug caused dialConn to instead write the per-request Proxy-Authorization
1377
+ // header through to the shared Header instance, introducing a data race.)
1378
+ func TestTransportProxyDialDoesNotMutateProxyConnectHeader (t * testing.T ) {
1379
+ setParallel (t )
1380
+ defer afterTest (t )
1381
+
1382
+ proxy := httptest .NewTLSServer (NotFoundHandler ())
1383
+ defer proxy .Close ()
1384
+ c := proxy .Client ()
1385
+
1386
+ tr := c .Transport .(* Transport )
1387
+ tr .Proxy = func (* Request ) (* url.URL , error ) {
1388
+ u , _ := url .Parse (proxy .URL )
1389
+ u .User = url .UserPassword ("aladdin" , "opensesame" )
1390
+ return u , nil
1391
+ }
1392
+ h := tr .ProxyConnectHeader
1393
+ if h == nil {
1394
+ h = make (Header )
1395
+ }
1396
+ tr .ProxyConnectHeader = make (Header , len (h ))
1397
+ for k , vals := range h {
1398
+ tr .ProxyConnectHeader [k ] = append ([]string (nil ), vals ... )
1399
+ }
1400
+
1401
+ req , err := NewRequest ("GET" , "https://golang.fake.tld/" , nil )
1402
+ if err != nil {
1403
+ t .Fatal (err )
1404
+ }
1405
+ _ , err = c .Do (req )
1406
+ if err == nil {
1407
+ t .Errorf ("unexpected Get success" )
1408
+ }
1409
+
1410
+ if ! reflect .DeepEqual (tr .ProxyConnectHeader , h ) {
1411
+ t .Errorf ("tr.ProxyConnectHeader = %v; want %v" , tr .ProxyConnectHeader , h )
1412
+ }
1413
+ }
1414
+
1374
1415
// TestTransportGzipRecursive sends a gzip quine and checks that the
1375
1416
// client gets the same value back. This is more cute than anything,
1376
1417
// but checks that we don't recurse forever, and checks that
0 commit comments