Browse Source

drain buffer correctly in httpupgrade (#3428)

* drain buffer correctly in httpupgrade

it seems the recently added httupgrade testsuite is causing timeouts on master

i have no evidence this is the real issue, but it feels to me that the
server could accidentally over-read, and then the encapsulated
connection will block forever trying to read data

let's test it in CI a couple of times, i don't have a way to reproduce
the issue

* correctly drain buffer, again
mmmray 1 year ago
parent
commit
f8ec93dfdd
1 changed files with 6 additions and 2 deletions
  1. 6 2
      transport/internet/httpupgrade/dialer.go

+ 6 - 2
transport/internet/httpupgrade/dialer.go

@@ -24,8 +24,10 @@ type ConnRF struct {
 func (c *ConnRF) Read(b []byte) (int, error) {
 	if c.First {
 		c.First = false
-		// TODO The bufio usage here is unreliable
-		resp, err := http.ReadResponse(bufio.NewReader(c.Conn), c.Req) // nolint:bodyclose
+		// create reader capped to size of `b`, so it can be fully drained into
+		// `b` later with a single Read call
+		reader := bufio.NewReaderSize(c.Conn, len(b))
+		resp, err := http.ReadResponse(reader, c.Req) // nolint:bodyclose
 		if err != nil {
 			return 0, err
 		}
@@ -34,6 +36,8 @@ func (c *ConnRF) Read(b []byte) (int, error) {
 			strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
 			return 0, newError("unrecognized reply")
 		}
+		// drain remaining bufreader
+		return reader.Read(b[:reader.Buffered()])
 	}
 	return c.Conn.Read(b)
 }