mirror of
https://github.com/golang/go
synced 2024-11-14 23:40:35 -07:00
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 <mknyszek@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
aa97a012b4
commit
fad6390f38
@ -21,9 +21,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type respTest struct {
|
type respTest struct {
|
||||||
Raw string
|
Raw string
|
||||||
Resp Response
|
RawOut string
|
||||||
Body string
|
Resp Response
|
||||||
|
Body string
|
||||||
}
|
}
|
||||||
|
|
||||||
func dummyReq(method string) *Request {
|
func dummyReq(method string) *Request {
|
||||||
@ -42,6 +43,11 @@ var respTests = []respTest{
|
|||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -66,6 +72,11 @@ var respTests = []respTest{
|
|||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -87,6 +98,9 @@ var respTests = []respTest{
|
|||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Body should not be read!\n",
|
"Body should not be read!\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 204 No Content\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "204 No Content",
|
Status: "204 No Content",
|
||||||
StatusCode: 204,
|
StatusCode: 204,
|
||||||
@ -110,6 +124,12 @@ var respTests = []respTest{
|
|||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Content-Length: 10\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -140,6 +160,14 @@ var respTests = []respTest{
|
|||||||
"0\r\n" +
|
"0\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Transfer-Encoding: chunked\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"13\r\n" +
|
||||||
|
"Body here\ncontinued\r\n" +
|
||||||
|
"0\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -165,6 +193,12 @@ var respTests = []respTest{
|
|||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Content-Length: 10\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -195,6 +229,14 @@ var respTests = []respTest{
|
|||||||
"0\r\n" +
|
"0\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Transfer-Encoding: chunked\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"a\r\n" +
|
||||||
|
"Body here\n\r\n" +
|
||||||
|
"0\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -217,6 +259,10 @@ var respTests = []respTest{
|
|||||||
"Transfer-Encoding: chunked\r\n" +
|
"Transfer-Encoding: chunked\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Transfer-Encoding: chunked\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -239,6 +285,11 @@ var respTests = []respTest{
|
|||||||
"Content-Length: 256\r\n" +
|
"Content-Length: 256\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-Length: 256\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -261,6 +312,10 @@ var respTests = []respTest{
|
|||||||
"Content-Length: 256\r\n" +
|
"Content-Length: 256\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Content-Length: 256\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -282,6 +337,10 @@ var respTests = []respTest{
|
|||||||
"HTTP/1.0 200 OK\r\n" +
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -304,6 +363,10 @@ var respTests = []respTest{
|
|||||||
"Content-Length: 0\r\n" +
|
"Content-Length: 0\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Content-Length: 0\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -325,6 +388,11 @@ var respTests = []respTest{
|
|||||||
// (permitted by RFC 7230, section 3.1.2)
|
// (permitted by RFC 7230, section 3.1.2)
|
||||||
{
|
{
|
||||||
"HTTP/1.0 303 \r\n\r\n",
|
"HTTP/1.0 303 \r\n\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 303 \r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "303 ",
|
Status: "303 ",
|
||||||
StatusCode: 303,
|
StatusCode: 303,
|
||||||
@ -344,6 +412,11 @@ var respTests = []respTest{
|
|||||||
// (not permitted by RFC 7230, but we'll accept it anyway)
|
// (not permitted by RFC 7230, but we'll accept it anyway)
|
||||||
{
|
{
|
||||||
"HTTP/1.0 303\r\n\r\n",
|
"HTTP/1.0 303\r\n\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 303 303\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "303",
|
Status: "303",
|
||||||
StatusCode: 303,
|
StatusCode: 303,
|
||||||
@ -366,6 +439,13 @@ Connection: close
|
|||||||
Content-Type: multipart/byteranges; boundary=18a75608c8f47cef
|
Content-Type: multipart/byteranges; boundary=18a75608c8f47cef
|
||||||
|
|
||||||
some body`,
|
some body`,
|
||||||
|
|
||||||
|
"HTTP/1.1 206 Partial Content\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-Type: multipart/byteranges; boundary=18a75608c8f47cef\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"some body",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "206 Partial Content",
|
Status: "206 Partial Content",
|
||||||
StatusCode: 206,
|
StatusCode: 206,
|
||||||
@ -390,6 +470,11 @@ some body`,
|
|||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -415,6 +500,14 @@ some body`,
|
|||||||
"Content-Length: 6\r\n\r\n" +
|
"Content-Length: 6\r\n\r\n" +
|
||||||
"foobar",
|
"foobar",
|
||||||
|
|
||||||
|
"HTTP/1.1 206 Partial Content\r\n" +
|
||||||
|
"Content-Length: 6\r\n" +
|
||||||
|
"Accept-Ranges: bytes\r\n" +
|
||||||
|
"Content-Range: bytes 0-5/1862\r\n" +
|
||||||
|
"Content-Type: text/plain; charset=utf-8\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"foobar",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "206 Partial Content",
|
Status: "206 Partial Content",
|
||||||
StatusCode: 206,
|
StatusCode: 206,
|
||||||
@ -441,6 +534,11 @@ some body`,
|
|||||||
"Connection: keep-alive, close\r\n" +
|
"Connection: keep-alive, close\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-Length: 256\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -467,6 +565,11 @@ some body`,
|
|||||||
"Connection: close\r\n" +
|
"Connection: close\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-Length: 256\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -493,6 +596,11 @@ some body`,
|
|||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -517,6 +625,12 @@ some body`,
|
|||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-Length: 10\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -541,6 +655,14 @@ some body`,
|
|||||||
"Connection: keep-alive\r\n" +
|
"Connection: keep-alive\r\n" +
|
||||||
"Keep-Alive: timeout=7200\r\n\r\n" +
|
"Keep-Alive: timeout=7200\r\n\r\n" +
|
||||||
"\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00s\xf3\xf7\a\x00\xab'\xd4\x1a\x03\x00\x00\x00",
|
"\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00s\xf3\xf7\a\x00\xab'\xd4\x1a\x03\x00\x00\x00",
|
||||||
|
|
||||||
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Content-Length: 23\r\n" +
|
||||||
|
"Connection: keep-alive\r\n" +
|
||||||
|
"Content-Encoding: gzip\r\n" +
|
||||||
|
"Keep-Alive: timeout=7200\r\n\r\n" +
|
||||||
|
"\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00s\xf3\xf7\a\x00\xab'\xd4\x1a\x03\x00\x00\x00",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
@ -566,6 +688,14 @@ some body`,
|
|||||||
"Content-type: text/html\r\n" +
|
"Content-type: text/html\r\n" +
|
||||||
"WWW-Authenticate: Basic realm=\"\"\r\n\r\n" +
|
"WWW-Authenticate: Basic realm=\"\"\r\n\r\n" +
|
||||||
"Your Authentication failed.\r\n",
|
"Your Authentication failed.\r\n",
|
||||||
|
|
||||||
|
"HTTP/1.0 401 Unauthorized\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-Type: text/html\r\n" +
|
||||||
|
"Www-Authenticate: Basic realm=\"\"\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Your Authentication failed.\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "401 Unauthorized",
|
Status: "401 Unauthorized",
|
||||||
StatusCode: 401,
|
StatusCode: 401,
|
||||||
@ -619,11 +749,18 @@ func TestWriteResponse(t *testing.T) {
|
|||||||
t.Errorf("#%d: %v", i, err)
|
t.Errorf("#%d: %v", i, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err = resp.Write(io.Discard)
|
var buf bytes.Buffer
|
||||||
|
err = resp.Write(&buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d: %v", i, err)
|
t.Errorf("#%d: %v", i, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if got, want := buf.String(), tt.RawOut; got != want {
|
||||||
|
t.Errorf("#%d: response differs; got:\n----\n%v\n----\nwant:\n----\n%v\n----\n",
|
||||||
|
i,
|
||||||
|
strings.ReplaceAll(got, "\r", "\\r"),
|
||||||
|
strings.ReplaceAll(want, "\r", "\\r"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +350,7 @@ func (t *transferWriter) writeBody(w io.Writer) (err error) {
|
|||||||
// nopCloser or readTrackingBody. This is to ensure that we can take advantage of
|
// nopCloser or readTrackingBody. This is to ensure that we can take advantage of
|
||||||
// OS-level optimizations in the event that the body is an
|
// OS-level optimizations in the event that the body is an
|
||||||
// *os.File.
|
// *os.File.
|
||||||
if t.Body != nil {
|
if !t.ResponseToHEAD && t.Body != nil {
|
||||||
var body = t.unwrapBody()
|
var body = t.unwrapBody()
|
||||||
if chunked(t.TransferEncoding) {
|
if chunked(t.TransferEncoding) {
|
||||||
if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
|
if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
|
||||||
@ -392,7 +392,7 @@ func (t *transferWriter) writeBody(w io.Writer) (err error) {
|
|||||||
t.ContentLength, ncopy)
|
t.ContentLength, ncopy)
|
||||||
}
|
}
|
||||||
|
|
||||||
if chunked(t.TransferEncoding) {
|
if !t.ResponseToHEAD && chunked(t.TransferEncoding) {
|
||||||
// Write Trailer header
|
// Write Trailer header
|
||||||
if t.Trailer != nil {
|
if t.Trailer != nil {
|
||||||
if err := t.Trailer.Write(w); err != nil {
|
if err := t.Trailer.Write(w); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user