aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/http/server.go')
-rw-r--r--src/net/http/server.go44
1 files changed, 34 insertions, 10 deletions
diff --git a/src/net/http/server.go b/src/net/http/server.go
index d44b0fb256..bc3a4633da 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -98,8 +98,8 @@ type ResponseWriter interface {
// Handlers can set HTTP trailers.
//
// Changing the header map after a call to WriteHeader (or
- // Write) has no effect unless the modified headers are
- // trailers.
+ // Write) has no effect unless the HTTP status code was of the
+ // 1xx class or the modified headers are trailers.
//
// There are two ways to set Trailers. The preferred way is to
// predeclare in the headers which trailers you will later
@@ -144,13 +144,18 @@ type ResponseWriter interface {
// If WriteHeader is not called explicitly, the first call to Write
// will trigger an implicit WriteHeader(http.StatusOK).
// Thus explicit calls to WriteHeader are mainly used to
- // send error codes.
+ // send error codes or 1xx informational responses.
//
// The provided code must be a valid HTTP 1xx-5xx status code.
- // Only one header may be written. Go does not currently
- // support sending user-defined 1xx informational headers,
- // with the exception of 100-continue response header that the
- // Server sends automatically when the Request.Body is read.
+ // Any number of 1xx headers may be written, followed by at most
+ // one 2xx-5xx header. 1xx headers are sent immediately, but 2xx-5xx
+ // headers may be buffered. Use the Flusher interface to send
+ // buffered data. The header map is cleared when 2xx-5xx headers are
+ // sent, but not with 1xx headers.
+ //
+ // The server will automatically send a 100 (Continue) header
+ // on the first read from the request body if the request has
+ // an "Expect: 100-continue" header.
WriteHeader(statusCode int)
}
@@ -420,7 +425,7 @@ type response struct {
req *Request // request for this response
reqBody io.ReadCloser
cancelCtx context.CancelFunc // when ServeHTTP exits
- wroteHeader bool // reply header has been (logically) written
+ wroteHeader bool // a non-1xx header has been (logically) written
wroteContinue bool // 100 Continue response was written
wants10KeepAlive bool // HTTP/1.0 w/ Connection "keep-alive"
wantsClose bool // HTTP request has Connection "close"
@@ -1100,8 +1105,7 @@ func checkWriteHeaderCode(code int) {
// Issue 22880: require valid WriteHeader status codes.
// For now we only enforce that it's three digits.
// In the future we might block things over 599 (600 and above aren't defined
- // at https://httpwg.org/specs/rfc7231.html#status.codes)
- // and we might block under 200 (once we have more mature 1xx support).
+ // at https://httpwg.org/specs/rfc7231.html#status.codes).
// But for now any three digits.
//
// We used to send "HTTP/1.1 000 0" on the wire in responses but there's
@@ -1144,6 +1148,26 @@ func (w *response) WriteHeader(code int) {
return
}
checkWriteHeaderCode(code)
+
+ // Handle informational headers
+ if code >= 100 && code <= 199 {
+ // Prevent a potential race with an automatically-sent 100 Continue triggered by Request.Body.Read()
+ if code == 100 && w.canWriteContinue.isSet() {
+ w.writeContinueMu.Lock()
+ w.canWriteContinue.setFalse()
+ w.writeContinueMu.Unlock()
+ }
+
+ writeStatusLine(w.conn.bufw, w.req.ProtoAtLeast(1, 1), code, w.statusBuf[:])
+
+ // Per RFC 8297 we must not clear the current header map
+ w.handlerHeader.WriteSubset(w.conn.bufw, excludedHeadersNoBody)
+ w.conn.bufw.Write(crlf)
+ w.conn.bufw.Flush()
+
+ return
+ }
+
w.wroteHeader = true
w.status = code