mirror of
https://github.com/golang/go
synced 2024-11-18 00:14:47 -07:00
net/http: make Transport.RoundTrip close body on any invalid request
Fixes #35015 Change-Id: I7a1ed9cfa219ad88014aad033e3a01f9dffc3eb3 Reviewed-on: https://go-review.googlesource.com/c/go/+/202239 Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
a7ce2ca52f
commit
ff9f7bc9da
@ -469,10 +469,12 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
|
|||||||
if isHTTP {
|
if isHTTP {
|
||||||
for k, vv := range req.Header {
|
for k, vv := range req.Header {
|
||||||
if !httpguts.ValidHeaderFieldName(k) {
|
if !httpguts.ValidHeaderFieldName(k) {
|
||||||
|
req.closeBody()
|
||||||
return nil, fmt.Errorf("net/http: invalid header field name %q", k)
|
return nil, fmt.Errorf("net/http: invalid header field name %q", k)
|
||||||
}
|
}
|
||||||
for _, v := range vv {
|
for _, v := range vv {
|
||||||
if !httpguts.ValidHeaderFieldValue(v) {
|
if !httpguts.ValidHeaderFieldValue(v) {
|
||||||
|
req.closeBody()
|
||||||
return nil, fmt.Errorf("net/http: invalid header field value %q for key %v", v, k)
|
return nil, fmt.Errorf("net/http: invalid header field value %q for key %v", v, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5730,21 +5730,87 @@ func (bc *bodyCloser) Read(b []byte) (n int, err error) {
|
|||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidMethodClosesBody(t *testing.T) {
|
// Issue 35015: ensure that Transport closes the body on any error
|
||||||
cst := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
|
// with an invalid request, as promised by Client.Do docs.
|
||||||
|
func TestTransportClosesBodyOnInvalidRequests(t *testing.T) {
|
||||||
|
cst := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||||
|
t.Errorf("Should not have been invoked")
|
||||||
|
}))
|
||||||
defer cst.Close()
|
defer cst.Close()
|
||||||
var bc bodyCloser
|
|
||||||
u, _ := url.Parse(cst.URL)
|
u, _ := url.Parse(cst.URL)
|
||||||
req := &Request{
|
|
||||||
Method: " ",
|
tests := []struct {
|
||||||
URL: u,
|
name string
|
||||||
Body: &bc,
|
req *Request
|
||||||
|
wantErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "invalid method",
|
||||||
|
req: &Request{
|
||||||
|
Method: " ",
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
|
wantErr: "invalid method",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil URL",
|
||||||
|
req: &Request{
|
||||||
|
Method: "GET",
|
||||||
|
},
|
||||||
|
wantErr: "nil Request.URL",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid header key",
|
||||||
|
req: &Request{
|
||||||
|
Method: "GET",
|
||||||
|
Header: Header{"💡": {"emoji"}},
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
|
wantErr: "invalid header field name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid header value",
|
||||||
|
req: &Request{
|
||||||
|
Method: "POST",
|
||||||
|
Header: Header{"key": {"\x19"}},
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
|
wantErr: "invalid header field value",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non HTTP(s) scheme",
|
||||||
|
req: &Request{
|
||||||
|
Method: "POST",
|
||||||
|
URL: &url.URL{Scheme: "faux"},
|
||||||
|
},
|
||||||
|
wantErr: "unsupported protocol scheme",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no Host in URL",
|
||||||
|
req: &Request{
|
||||||
|
Method: "POST",
|
||||||
|
URL: &url.URL{Scheme: "http"},
|
||||||
|
},
|
||||||
|
wantErr: "no Host",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
_, err := DefaultClient.Do(req)
|
|
||||||
if err == nil {
|
for _, tt := range tests {
|
||||||
t.Fatal("Expected an error")
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
}
|
var bc bodyCloser
|
||||||
if !bc {
|
req := tt.req
|
||||||
t.Fatal("Expected body to have been closed")
|
req.Body = &bc
|
||||||
|
_, err := DefaultClient.Do(tt.req)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("Expected an error")
|
||||||
|
}
|
||||||
|
if !bc {
|
||||||
|
t.Fatal("Expected body to have been closed")
|
||||||
|
}
|
||||||
|
if g, w := err.Error(), tt.wantErr; !strings.Contains(g, w) {
|
||||||
|
t.Fatalf("Error mismatch\n\t%q\ndoes not contain\n\t%q", g, w)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user