mirror of
https://github.com/golang/go.git
synced 2025-05-28 10:51:22 +00:00
net/http: don't reuse conns after incomplete 100-continue requests
If we receive an HTTP request with "Expect: 100-continue" and the Handler never read to EOF, the conn is in an unknown state. Don't reuse that connection. Fixes #11549 Change-Id: I5be93e7a54e899d615b05f72bdcf12b25304bc60 Reviewed-on: https://go-review.googlesource.com/12262 Reviewed-by: Andrew Gerrand <adg@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
2b9e5a7165
commit
88fc3587ec
@ -2991,6 +2991,49 @@ func TestTolerateCRLFBeforeRequestLine(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue11549_Expect100(t *testing.T) {
|
||||
req := reqBytes(`PUT /readbody HTTP/1.1
|
||||
User-Agent: PycURL/7.22.0
|
||||
Host: 127.0.0.1:9000
|
||||
Accept: */*
|
||||
Expect: 100-continue
|
||||
Content-Length: 10
|
||||
|
||||
HelloWorldPUT /noreadbody HTTP/1.1
|
||||
User-Agent: PycURL/7.22.0
|
||||
Host: 127.0.0.1:9000
|
||||
Accept: */*
|
||||
Expect: 100-continue
|
||||
Content-Length: 10
|
||||
|
||||
GET /should-be-ignored HTTP/1.1
|
||||
Host: foo
|
||||
|
||||
`)
|
||||
var buf bytes.Buffer
|
||||
conn := &rwTestConn{
|
||||
Reader: bytes.NewReader(req),
|
||||
Writer: &buf,
|
||||
closec: make(chan bool, 1),
|
||||
}
|
||||
ln := &oneConnListener{conn: conn}
|
||||
numReq := 0
|
||||
go Serve(ln, HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||
numReq++
|
||||
if r.URL.Path == "/readbody" {
|
||||
ioutil.ReadAll(r.Body)
|
||||
}
|
||||
io.WriteString(w, "Hello world!")
|
||||
}))
|
||||
<-conn.closec
|
||||
if numReq != 2 {
|
||||
t.Errorf("num requests = %d; want 2", numReq)
|
||||
}
|
||||
if !strings.Contains(buf.String(), "Connection: close\r\n") {
|
||||
t.Errorf("expected 'Connection: close' in response; got: %s", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkClientServer(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.StopTimer()
|
||||
|
@ -554,6 +554,7 @@ type expectContinueReader struct {
|
||||
resp *response
|
||||
readCloser io.ReadCloser
|
||||
closed bool
|
||||
sawEOF bool
|
||||
}
|
||||
|
||||
func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
|
||||
@ -565,7 +566,11 @@ func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
|
||||
ecr.resp.conn.buf.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
|
||||
ecr.resp.conn.buf.Flush()
|
||||
}
|
||||
return ecr.readCloser.Read(p)
|
||||
n, err = ecr.readCloser.Read(p)
|
||||
if err == io.EOF {
|
||||
ecr.sawEOF = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ecr *expectContinueReader) Close() error {
|
||||
@ -846,6 +851,22 @@ func (cw *chunkWriter) writeHeader(p []byte) {
|
||||
w.closeAfterReply = true
|
||||
}
|
||||
|
||||
// If the client wanted a 100-continue but we never sent it to
|
||||
// them (or, more strictly: we never finished reading their
|
||||
// request body), don't reuse this connection because it's now
|
||||
// in an unknown state: we might be sending this response at
|
||||
// the same time the client is now sending its request body
|
||||
// after a timeout. (Some HTTP clients send Expect:
|
||||
// 100-continue but knowing that some servers don't support
|
||||
// it, the clients set a timer and send the body later anyway)
|
||||
// If we haven't seen EOF, we can't skip over the unread body
|
||||
// because we don't know if the next bytes on the wire will be
|
||||
// the body-following-the-timer or the subsequent request.
|
||||
// See Issue 11549.
|
||||
if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF {
|
||||
w.closeAfterReply = true
|
||||
}
|
||||
|
||||
// Per RFC 2616, we should consume the request body before
|
||||
// replying, if the handler hasn't already done so. But we
|
||||
// don't want to do an unbounded amount of reading here for
|
||||
|
Loading…
x
Reference in New Issue
Block a user