mirror of
https://github.com/golang/go
synced 2024-11-23 07:00:05 -07:00
net/http: tolerate old buggy user agents, per RFC 2616 section 4.1
Some old buggy browsers sent extra CRLF(s) after POST bodies. Skip over them before reading subsequent requests. Fixes #10876 Change-Id: I62eacf2b3e985caffa85aee3de39d8cd3548130b Reviewed-on: https://go-review.googlesource.com/11491 Reviewed-by: Andrew Gerrand <adg@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
fe1cecfaec
commit
bf5e19fbaf
@ -2963,6 +2963,30 @@ func TestNoContentLengthIfTransferEncoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// tolerate extra CRLF(s) before Request-Line on subsequent requests on a conn
|
||||
// Issue 10876.
|
||||
func TestTolerateCRLFBeforeRequestLine(t *testing.T) {
|
||||
req := []byte("POST / HTTP/1.1\r\nHost: golang.org\r\nContent-Length: 3\r\n\r\nABC" +
|
||||
"\r\n\r\n" + // <-- this stuff is bogus, but we'll ignore it
|
||||
"GET / HTTP/1.1\r\nHost: golang.org\r\n\r\n")
|
||||
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(rw ResponseWriter, r *Request) {
|
||||
numReq++
|
||||
}))
|
||||
<-conn.closec
|
||||
if numReq != 2 {
|
||||
t.Errorf("num requests = %d; want 2", numReq)
|
||||
t.Logf("Res: %s", buf.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkClientServer(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.StopTimer()
|
||||
|
@ -130,6 +130,7 @@ type conn struct {
|
||||
lr *io.LimitedReader // io.LimitReader(sr)
|
||||
buf *bufio.ReadWriter // buffered(lr,rwc), reading from bufio->limitReader->sr->rwc
|
||||
tlsState *tls.ConnectionState // or nil when not using TLS
|
||||
lastMethod string // method of previous request, or ""
|
||||
|
||||
mu sync.Mutex // guards the following
|
||||
clientGone bool // if client has disconnected mid-request
|
||||
@ -618,6 +619,11 @@ func (c *conn) readRequest() (w *response, err error) {
|
||||
}
|
||||
|
||||
c.lr.N = c.server.initialLimitedReaderSize()
|
||||
if c.lastMethod == "POST" {
|
||||
// RFC 2616 section 4.1 tolerance for old buggy clients.
|
||||
peek, _ := c.buf.Reader.Peek(4) // ReadRequest will get err below
|
||||
c.buf.Reader.Discard(numLeadingCRorLF(peek))
|
||||
}
|
||||
var req *Request
|
||||
if req, err = ReadRequest(c.buf.Reader); err != nil {
|
||||
if c.lr.N == 0 {
|
||||
@ -626,6 +632,7 @@ func (c *conn) readRequest() (w *response, err error) {
|
||||
return nil, err
|
||||
}
|
||||
c.lr.N = noLimit
|
||||
c.lastMethod = req.Method
|
||||
|
||||
req.RemoteAddr = c.remoteAddr
|
||||
req.TLS = c.tlsState
|
||||
@ -2181,3 +2188,15 @@ func (w checkConnErrorWriter) Write(p []byte) (n int, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func numLeadingCRorLF(v []byte) (n int) {
|
||||
for _, b := range v {
|
||||
if b == '\r' || b == '\n' {
|
||||
n++
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user