@@ -1424,3 +1424,59 @@ func testWriteHeader0(t *testing.T, h2 bool) {
1424
1424
t .Error ("expected panic in handler" )
1425
1425
}
1426
1426
}
1427
+
1428
+ // Issue 23010: don't be super strict checking WriteHeader's code if
1429
+ // it's not even valid to call WriteHeader then anyway.
1430
+ func TestWriteHeaderNoCodeCheck_h1 (t * testing.T ) { testWriteHeaderAfterWrite (t , h1Mode , false ) }
1431
+ func TestWriteHeaderNoCodeCheck_h1hijack (t * testing.T ) { testWriteHeaderAfterWrite (t , h1Mode , true ) }
1432
+ func TestWriteHeaderNoCodeCheck_h2 (t * testing.T ) { testWriteHeaderAfterWrite (t , h2Mode , false ) }
1433
+ func testWriteHeaderAfterWrite (t * testing.T , h2 , hijack bool ) {
1434
+ setParallel (t )
1435
+ defer afterTest (t )
1436
+
1437
+ var errorLog lockedBytesBuffer
1438
+ cst := newClientServerTest (t , h2 , HandlerFunc (func (w ResponseWriter , r * Request ) {
1439
+ if hijack {
1440
+ conn , _ , _ := w .(Hijacker ).Hijack ()
1441
+ defer conn .Close ()
1442
+ conn .Write ([]byte ("HTTP/1.1 200 OK\r \n Content-Length: 6\r \n \r \n foo" ))
1443
+ w .WriteHeader (0 ) // verify this doesn't panic if there's already output; Issue 23010
1444
+ conn .Write ([]byte ("bar" ))
1445
+ return
1446
+ }
1447
+ io .WriteString (w , "foo" )
1448
+ w .(Flusher ).Flush ()
1449
+ w .WriteHeader (0 ) // verify this doesn't panic if there's already output; Issue 23010
1450
+ io .WriteString (w , "bar" )
1451
+ }), func (ts * httptest.Server ) {
1452
+ ts .Config .ErrorLog = log .New (& errorLog , "" , 0 )
1453
+ })
1454
+ defer cst .close ()
1455
+ res , err := cst .c .Get (cst .ts .URL )
1456
+ if err != nil {
1457
+ t .Fatal (err )
1458
+ }
1459
+ defer res .Body .Close ()
1460
+ body , err := ioutil .ReadAll (res .Body )
1461
+ if err != nil {
1462
+ t .Fatal (err )
1463
+ }
1464
+ if got , want := string (body ), "foobar" ; got != want {
1465
+ t .Errorf ("got = %q; want %q" , got , want )
1466
+ }
1467
+
1468
+ // Also check the stderr output:
1469
+ if h2 {
1470
+ // TODO: also emit this log message for HTTP/2?
1471
+ // We historically haven't, so don't check.
1472
+ return
1473
+ }
1474
+ gotLog := strings .TrimSpace (errorLog .String ())
1475
+ wantLog := "http: multiple response.WriteHeader calls"
1476
+ if hijack {
1477
+ wantLog = "http: response.WriteHeader on hijacked connection"
1478
+ }
1479
+ if gotLog != wantLog {
1480
+ t .Errorf ("stderr output = %q; want %q" , gotLog , wantLog )
1481
+ }
1482
+ }
0 commit comments