Skip to content

Commit 625722d

Browse files
neildpull[bot]
authored andcommitted
net/http: don't write body for HEAD responses in Response.Write
Fixes #62015 Change-Id: I88c5427f85e740d5b956942bb1c2727dac2935ea Reviewed-on: https://go-review.googlesource.com/c/go/+/601238 Reviewed-by: Michael Knyszek <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent dea5435 commit 625722d

File tree

2 files changed

+143
-6
lines changed

2 files changed

+143
-6
lines changed

src/net/http/response_test.go

Lines changed: 141 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ import (
2121
)
2222

2323
type respTest struct {
24-
Raw string
25-
Resp Response
26-
Body string
24+
Raw string
25+
RawOut string
26+
Resp Response
27+
Body string
2728
}
2829

2930
func dummyReq(method string) *Request {
@@ -42,6 +43,11 @@ var respTests = []respTest{
4243
"\r\n" +
4344
"Body here\n",
4445

46+
"HTTP/1.0 200 OK\r\n" +
47+
"Connection: close\r\n" +
48+
"\r\n" +
49+
"Body here\n",
50+
4551
Response{
4652
Status: "200 OK",
4753
StatusCode: 200,
@@ -66,6 +72,11 @@ var respTests = []respTest{
6672
"\r\n" +
6773
"Body here\n",
6874

75+
"HTTP/1.1 200 OK\r\n" +
76+
"Connection: close\r\n" +
77+
"\r\n" +
78+
"Body here\n",
79+
6980
Response{
7081
Status: "200 OK",
7182
StatusCode: 200,
@@ -87,6 +98,9 @@ var respTests = []respTest{
8798
"\r\n" +
8899
"Body should not be read!\n",
89100

101+
"HTTP/1.1 204 No Content\r\n" +
102+
"\r\n",
103+
90104
Response{
91105
Status: "204 No Content",
92106
StatusCode: 204,
@@ -110,6 +124,12 @@ var respTests = []respTest{
110124
"\r\n" +
111125
"Body here\n",
112126

127+
"HTTP/1.0 200 OK\r\n" +
128+
"Content-Length: 10\r\n" +
129+
"Connection: close\r\n" +
130+
"\r\n" +
131+
"Body here\n",
132+
113133
Response{
114134
Status: "200 OK",
115135
StatusCode: 200,
@@ -140,6 +160,14 @@ var respTests = []respTest{
140160
"0\r\n" +
141161
"\r\n",
142162

163+
"HTTP/1.1 200 OK\r\n" +
164+
"Transfer-Encoding: chunked\r\n" +
165+
"\r\n" +
166+
"13\r\n" +
167+
"Body here\ncontinued\r\n" +
168+
"0\r\n" +
169+
"\r\n",
170+
143171
Response{
144172
Status: "200 OK",
145173
StatusCode: 200,
@@ -165,6 +193,12 @@ var respTests = []respTest{
165193
"\r\n" +
166194
"Body here\n",
167195

196+
"HTTP/1.0 200 OK\r\n" +
197+
"Content-Length: 10\r\n" +
198+
"Connection: close\r\n" +
199+
"\r\n" +
200+
"Body here\n",
201+
168202
Response{
169203
Status: "200 OK",
170204
StatusCode: 200,
@@ -195,6 +229,14 @@ var respTests = []respTest{
195229
"0\r\n" +
196230
"\r\n",
197231

232+
"HTTP/1.1 200 OK\r\n" +
233+
"Transfer-Encoding: chunked\r\n" +
234+
"\r\n" +
235+
"a\r\n" +
236+
"Body here\n\r\n" +
237+
"0\r\n" +
238+
"\r\n",
239+
198240
Response{
199241
Status: "200 OK",
200242
StatusCode: 200,
@@ -217,6 +259,10 @@ var respTests = []respTest{
217259
"Transfer-Encoding: chunked\r\n" +
218260
"\r\n",
219261

262+
"HTTP/1.1 200 OK\r\n" +
263+
"Transfer-Encoding: chunked\r\n" +
264+
"\r\n",
265+
220266
Response{
221267
Status: "200 OK",
222268
StatusCode: 200,
@@ -239,6 +285,11 @@ var respTests = []respTest{
239285
"Content-Length: 256\r\n" +
240286
"\r\n",
241287

288+
"HTTP/1.0 200 OK\r\n" +
289+
"Connection: close\r\n" +
290+
"Content-Length: 256\r\n" +
291+
"\r\n",
292+
242293
Response{
243294
Status: "200 OK",
244295
StatusCode: 200,
@@ -261,6 +312,10 @@ var respTests = []respTest{
261312
"Content-Length: 256\r\n" +
262313
"\r\n",
263314

315+
"HTTP/1.1 200 OK\r\n" +
316+
"Content-Length: 256\r\n" +
317+
"\r\n",
318+
264319
Response{
265320
Status: "200 OK",
266321
StatusCode: 200,
@@ -282,6 +337,10 @@ var respTests = []respTest{
282337
"HTTP/1.0 200 OK\r\n" +
283338
"\r\n",
284339

340+
"HTTP/1.0 200 OK\r\n" +
341+
"Connection: close\r\n" +
342+
"\r\n",
343+
285344
Response{
286345
Status: "200 OK",
287346
StatusCode: 200,
@@ -304,6 +363,10 @@ var respTests = []respTest{
304363
"Content-Length: 0\r\n" +
305364
"\r\n",
306365

366+
"HTTP/1.1 200 OK\r\n" +
367+
"Content-Length: 0\r\n" +
368+
"\r\n",
369+
307370
Response{
308371
Status: "200 OK",
309372
StatusCode: 200,
@@ -325,6 +388,11 @@ var respTests = []respTest{
325388
// (permitted by RFC 7230, section 3.1.2)
326389
{
327390
"HTTP/1.0 303 \r\n\r\n",
391+
392+
"HTTP/1.0 303 \r\n" +
393+
"Connection: close\r\n" +
394+
"\r\n",
395+
328396
Response{
329397
Status: "303 ",
330398
StatusCode: 303,
@@ -344,6 +412,11 @@ var respTests = []respTest{
344412
// (not permitted by RFC 7230, but we'll accept it anyway)
345413
{
346414
"HTTP/1.0 303\r\n\r\n",
415+
416+
"HTTP/1.0 303 303\r\n" +
417+
"Connection: close\r\n" +
418+
"\r\n",
419+
347420
Response{
348421
Status: "303",
349422
StatusCode: 303,
@@ -366,6 +439,13 @@ Connection: close
366439
Content-Type: multipart/byteranges; boundary=18a75608c8f47cef
367440
368441
some body`,
442+
443+
"HTTP/1.1 206 Partial Content\r\n" +
444+
"Connection: close\r\n" +
445+
"Content-Type: multipart/byteranges; boundary=18a75608c8f47cef\r\n" +
446+
"\r\n" +
447+
"some body",
448+
369449
Response{
370450
Status: "206 Partial Content",
371451
StatusCode: 206,
@@ -390,6 +470,11 @@ some body`,
390470
"\r\n" +
391471
"Body here\n",
392472

473+
"HTTP/1.0 200 OK\r\n" +
474+
"Connection: close\r\n" +
475+
"\r\n" +
476+
"Body here\n",
477+
393478
Response{
394479
Status: "200 OK",
395480
StatusCode: 200,
@@ -415,6 +500,14 @@ some body`,
415500
"Content-Length: 6\r\n\r\n" +
416501
"foobar",
417502

503+
"HTTP/1.1 206 Partial Content\r\n" +
504+
"Content-Length: 6\r\n" +
505+
"Accept-Ranges: bytes\r\n" +
506+
"Content-Range: bytes 0-5/1862\r\n" +
507+
"Content-Type: text/plain; charset=utf-8\r\n" +
508+
"\r\n" +
509+
"foobar",
510+
418511
Response{
419512
Status: "206 Partial Content",
420513
StatusCode: 206,
@@ -441,6 +534,11 @@ some body`,
441534
"Connection: keep-alive, close\r\n" +
442535
"\r\n",
443536

537+
"HTTP/1.1 200 OK\r\n" +
538+
"Connection: close\r\n" +
539+
"Content-Length: 256\r\n" +
540+
"\r\n",
541+
444542
Response{
445543
Status: "200 OK",
446544
StatusCode: 200,
@@ -467,6 +565,11 @@ some body`,
467565
"Connection: close\r\n" +
468566
"\r\n",
469567

568+
"HTTP/1.1 200 OK\r\n" +
569+
"Connection: close\r\n" +
570+
"Content-Length: 256\r\n" +
571+
"\r\n",
572+
470573
Response{
471574
Status: "200 OK",
472575
StatusCode: 200,
@@ -493,6 +596,11 @@ some body`,
493596
"\r\n" +
494597
"Body here\n",
495598

599+
"HTTP/1.0 200 OK\r\n" +
600+
"Connection: close\r\n" +
601+
"\r\n" +
602+
"Body here\n",
603+
496604
Response{
497605
Status: "200 OK",
498606
StatusCode: 200,
@@ -517,6 +625,12 @@ some body`,
517625
"\r\n" +
518626
"Body here\n",
519627

628+
"HTTP/1.0 200 OK\r\n" +
629+
"Connection: close\r\n" +
630+
"Content-Length: 10\r\n" +
631+
"\r\n" +
632+
"Body here\n",
633+
520634
Response{
521635
Status: "200 OK",
522636
StatusCode: 200,
@@ -541,6 +655,14 @@ some body`,
541655
"Connection: keep-alive\r\n" +
542656
"Keep-Alive: timeout=7200\r\n\r\n" +
543657
"\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00s\xf3\xf7\a\x00\xab'\xd4\x1a\x03\x00\x00\x00",
658+
659+
"HTTP/1.1 200 OK\r\n" +
660+
"Content-Length: 23\r\n" +
661+
"Connection: keep-alive\r\n" +
662+
"Content-Encoding: gzip\r\n" +
663+
"Keep-Alive: timeout=7200\r\n\r\n" +
664+
"\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00s\xf3\xf7\a\x00\xab'\xd4\x1a\x03\x00\x00\x00",
665+
544666
Response{
545667
Status: "200 OK",
546668
StatusCode: 200,
@@ -566,6 +688,14 @@ some body`,
566688
"Content-type: text/html\r\n" +
567689
"WWW-Authenticate: Basic realm=\"\"\r\n\r\n" +
568690
"Your Authentication failed.\r\n",
691+
692+
"HTTP/1.0 401 Unauthorized\r\n" +
693+
"Connection: close\r\n" +
694+
"Content-Type: text/html\r\n" +
695+
"Www-Authenticate: Basic realm=\"\"\r\n" +
696+
"\r\n" +
697+
"Your Authentication failed.\r\n",
698+
569699
Response{
570700
Status: "401 Unauthorized",
571701
StatusCode: 401,
@@ -619,11 +749,18 @@ func TestWriteResponse(t *testing.T) {
619749
t.Errorf("#%d: %v", i, err)
620750
continue
621751
}
622-
err = resp.Write(io.Discard)
752+
var buf bytes.Buffer
753+
err = resp.Write(&buf)
623754
if err != nil {
624755
t.Errorf("#%d: %v", i, err)
625756
continue
626757
}
758+
if got, want := buf.String(), tt.RawOut; got != want {
759+
t.Errorf("#%d: response differs; got:\n----\n%v\n----\nwant:\n----\n%v\n----\n",
760+
i,
761+
strings.ReplaceAll(got, "\r", "\\r"),
762+
strings.ReplaceAll(want, "\r", "\\r"))
763+
}
627764
}
628765
}
629766

src/net/http/transfer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ func (t *transferWriter) writeBody(w io.Writer) (err error) {
350350
// nopCloser or readTrackingBody. This is to ensure that we can take advantage of
351351
// OS-level optimizations in the event that the body is an
352352
// *os.File.
353-
if t.Body != nil {
353+
if !t.ResponseToHEAD && t.Body != nil {
354354
var body = t.unwrapBody()
355355
if chunked(t.TransferEncoding) {
356356
if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
@@ -392,7 +392,7 @@ func (t *transferWriter) writeBody(w io.Writer) (err error) {
392392
t.ContentLength, ncopy)
393393
}
394394

395-
if chunked(t.TransferEncoding) {
395+
if !t.ResponseToHEAD && chunked(t.TransferEncoding) {
396396
// Write Trailer header
397397
if t.Trailer != nil {
398398
if err := t.Trailer.Write(w); err != nil {

0 commit comments

Comments
 (0)