From 9a57fa31ff35024b9f628e7eae39bfd35bf90d77 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 10 May 2016 16:09:16 -0700 Subject: [PATCH] net/http: document ResponseWriter read-vs-write concurrency rules Summary: Go's HTTP/1.x server closes the request body once writes are flushed. Go's HTTP/2 server supports concurrent read & write. Added a TODO to make the HTTP/1.x server also support concurrent read+write. But for now, document it. Updates #15527 Change-Id: I81f7354923d37bfc1632629679c75c06a62bb584 Reviewed-on: https://go-review.googlesource.com/23011 Reviewed-by: Andrew Gerrand --- src/net/http/server.go | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/net/http/server.go b/src/net/http/server.go index 23fb84fcdab..e24777421cf 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -91,10 +91,24 @@ type ResponseWriter interface { Header() Header // Write writes the data to the connection as part of an HTTP reply. - // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK) - // before writing the data. If the Header does not contain a - // Content-Type line, Write adds a Content-Type set to the result of passing - // the initial 512 bytes of written data to DetectContentType. + // + // If WriteHeader has not yet been called, Write calls + // WriteHeader(http.StatusOK) before writing the data. If the Header + // does not contain a Content-Type line, Write adds a Content-Type set + // to the result of passing the initial 512 bytes of written data to + // DetectContentType. + // + // Depending on the HTTP protocol version and the client, calling + // Write or WriteHeader may prevent future reads on the + // Request.Body. For HTTP/1.x requests, handlers should read any + // needed request body data before writing the response. Once the + // headers have been flushed (due to either an explicit Flusher.Flush + // call or writing enough data to trigger a flush), the request body + // may be unavailable. For HTTP/2 requests, the Go HTTP server permits + // handlers to continue to read the request body while concurrently + // writing the response. However, such behavior may not be supported + // by all HTTP/2 clients. Handlers should read before writing if + // possible to maximize compatibility. Write([]byte) (int, error) // WriteHeader sends an HTTP response header with status code. @@ -1027,6 +1041,9 @@ func (cw *chunkWriter) writeHeader(p []byte) { // replying, if the handler hasn't already done so. But we // don't want to do an unbounded amount of reading here for // DoS reasons, so we only try up to a threshold. + // TODO(bradfitz): where does RFC 2616 say that? See Issue 15527 + // about HTTP/1.x Handlers concurrently reading and writing, like + // HTTP/2 handlers can do. Maybe this code should be relaxed? if w.req.ContentLength != 0 && !w.closeAfterReply { var discard, tooBig bool