diff options
author | Ian Lance Taylor <iant@google.com> | 2016-02-03 21:58:02 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-02-03 21:58:02 +0000 |
commit | f98dd1a338867a408f7c72d73fbad7fe7fc93e3a (patch) | |
tree | 2f8da9862a9c1fe0df138917f997b03439c02773 /libgo/go/net/http/server.go | |
parent | b081ed4efc144da0c45a6484aebfd10e0eb9fda3 (diff) | |
download | gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.zip gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.tar.gz gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.tar.bz2 |
libgo: Update to go1.6rc1.
Reviewed-on: https://go-review.googlesource.com/19200
From-SVN: r233110
Diffstat (limited to 'libgo/go/net/http/server.go')
-rw-r--r-- | libgo/go/net/http/server.go | 729 |
1 files changed, 514 insertions, 215 deletions
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go index a3e4355..004a1f9 100644 --- a/libgo/go/net/http/server.go +++ b/libgo/go/net/http/server.go @@ -8,6 +8,7 @@ package http import ( "bufio" + "bytes" "crypto/tls" "errors" "fmt" @@ -35,26 +36,33 @@ var ( ErrContentLength = errors.New("Conn.Write wrote more than the declared Content-Length") ) -// Objects implementing the Handler interface can be -// registered to serve a particular path or subtree -// in the HTTP server. +// A Handler responds to an HTTP request. // // ServeHTTP should write reply headers and data to the ResponseWriter -// and then return. Returning signals that the request is finished -// and that the HTTP server can move on to the next request on -// the connection. +// and then return. Returning signals that the request is finished; it +// is not valid to use the ResponseWriter or read from the +// Request.Body after or concurrently with the completion of the +// ServeHTTP call. +// +// Depending on the HTTP client software, HTTP protocol version, and +// any intermediaries between the client and the Go server, it may not +// be possible to read from the Request.Body after writing to the +// ResponseWriter. Cautious handlers should read the Request.Body +// first, and then reply. // // If ServeHTTP panics, the server (the caller of ServeHTTP) assumes // that the effect of the panic was isolated to the active request. // It recovers the panic, logs a stack trace to the server error log, // and hangs up the connection. -// type Handler interface { ServeHTTP(ResponseWriter, *Request) } // A ResponseWriter interface is used by an HTTP handler to // construct an HTTP response. +// +// A ResponseWriter may not be used after the Handler.ServeHTTP method +// has returned. type ResponseWriter interface { // Header returns the header map that will be sent by // WriteHeader. Changing the header after a call to @@ -114,28 +122,76 @@ type Hijacker interface { // This mechanism can be used to cancel long operations on the server // if the client has disconnected before the response is ready. type CloseNotifier interface { - // CloseNotify returns a channel that receives a single value - // when the client connection has gone away. + // CloseNotify returns a channel that receives at most a + // single value (true) when the client connection has gone + // away. + // + // CloseNotify may wait to notify until Request.Body has been + // fully read. + // + // After the Handler has returned, there is no guarantee + // that the channel receives a value. + // + // If the protocol is HTTP/1.1 and CloseNotify is called while + // processing an idempotent request (such a GET) while + // HTTP/1.1 pipelining is in use, the arrival of a subsequent + // pipelined request may cause a value to be sent on the + // returned channel. In practice HTTP/1.1 pipelining is not + // enabled in browsers and not seen often in the wild. If this + // is a problem, use HTTP/2 or only use CloseNotify on methods + // such as POST. CloseNotify() <-chan bool } // A conn represents the server side of an HTTP connection. type conn struct { - remoteAddr string // network address of remote side - server *Server // the Server on which the connection arrived - rwc net.Conn // i/o connection - w io.Writer // checkConnErrorWriter's copy of wrc, not zeroed on Hijack - werr error // any errors writing to w - sr liveSwitchReader // where the LimitReader reads from; usually the rwc - 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 - closeNotifyc chan bool // made lazily - hijackedv bool // connection has been hijacked by handler + // server is the server on which the connection arrived. + // Immutable; never nil. + server *Server + + // rwc is the underlying network connection. + // This is never wrapped by other types and is the value given out + // to CloseNotifier callers. It is usually of type *net.TCPConn or + // *tls.Conn. + rwc net.Conn + + // remoteAddr is rwc.RemoteAddr().String(). It is not populated synchronously + // inside the Listener's Accept goroutine, as some implementations block. + // It is populated immediately inside the (*conn).serve goroutine. + // This is the value of a Handler's (*Request).RemoteAddr. + remoteAddr string + + // tlsState is the TLS connection state when using TLS. + // nil means not TLS. + tlsState *tls.ConnectionState + + // werr is set to the first write error to rwc. + // It is set via checkConnErrorWriter{w}, where bufw writes. + werr error + + // r is bufr's read source. It's a wrapper around rwc that provides + // io.LimitedReader-style limiting (while reading request headers) + // and functionality to support CloseNotifier. See *connReader docs. + r *connReader + + // bufr reads from r. + // Users of bufr must hold mu. + bufr *bufio.Reader + + // bufw writes to checkConnErrorWriter{c}, which populates werr on error. + bufw *bufio.Writer + + // lastMethod is the method of the most recent request + // on this connection, if any. + lastMethod string + + // mu guards hijackedv, use of bufr, (*response).closeNotifyCh. + mu sync.Mutex + + // hijackedv is whether this connection has been hijacked + // by a Handler with the Hijacker interface. + // It is guarded by mu. + hijackedv bool } func (c *conn) hijacked() bool { @@ -144,81 +200,18 @@ func (c *conn) hijacked() bool { return c.hijackedv } -func (c *conn) hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) { - c.mu.Lock() - defer c.mu.Unlock() +// c.mu must be held. +func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) { if c.hijackedv { return nil, nil, ErrHijacked } - if c.closeNotifyc != nil { - return nil, nil, errors.New("http: Hijack is incompatible with use of CloseNotifier") - } c.hijackedv = true rwc = c.rwc - buf = c.buf - c.rwc = nil - c.buf = nil + buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc)) c.setState(rwc, StateHijacked) return } -func (c *conn) closeNotify() <-chan bool { - c.mu.Lock() - defer c.mu.Unlock() - if c.closeNotifyc == nil { - c.closeNotifyc = make(chan bool, 1) - if c.hijackedv { - // to obey the function signature, even though - // it'll never receive a value. - return c.closeNotifyc - } - pr, pw := io.Pipe() - - readSource := c.sr.r - c.sr.Lock() - c.sr.r = pr - c.sr.Unlock() - go func() { - _, err := io.Copy(pw, readSource) - if err == nil { - err = io.EOF - } - pw.CloseWithError(err) - c.noteClientGone() - }() - } - return c.closeNotifyc -} - -func (c *conn) noteClientGone() { - c.mu.Lock() - defer c.mu.Unlock() - if c.closeNotifyc != nil && !c.clientGone { - c.closeNotifyc <- true - } - c.clientGone = true -} - -// A switchWriter can have its Writer changed at runtime. -// It's not safe for concurrent Writes and switches. -type switchWriter struct { - io.Writer -} - -// A liveSwitchReader can have its Reader changed at runtime. It's -// safe for concurrent reads and switches, if its mutex is held. -type liveSwitchReader struct { - sync.Mutex - r io.Reader -} - -func (sr *liveSwitchReader) Read(p []byte) (n int, err error) { - sr.Lock() - r := sr.r - sr.Unlock() - return r.Read(p) -} - // This should be >= 512 bytes for DetectContentType, // but otherwise it's somewhat arbitrary. const bufferBeforeChunkingSize = 2048 @@ -265,15 +258,15 @@ func (cw *chunkWriter) Write(p []byte) (n int, err error) { return len(p), nil } if cw.chunking { - _, err = fmt.Fprintf(cw.res.conn.buf, "%x\r\n", len(p)) + _, err = fmt.Fprintf(cw.res.conn.bufw, "%x\r\n", len(p)) if err != nil { cw.res.conn.rwc.Close() return } } - n, err = cw.res.conn.buf.Write(p) + n, err = cw.res.conn.bufw.Write(p) if cw.chunking && err == nil { - _, err = cw.res.conn.buf.Write(crlf) + _, err = cw.res.conn.bufw.Write(crlf) } if err != nil { cw.res.conn.rwc.Close() @@ -285,7 +278,7 @@ func (cw *chunkWriter) flush() { if !cw.wroteHeader { cw.writeHeader(nil) } - cw.res.conn.buf.Flush() + cw.res.conn.bufw.Flush() } func (cw *chunkWriter) close() { @@ -293,7 +286,7 @@ func (cw *chunkWriter) close() { cw.writeHeader(nil) } if cw.chunking { - bw := cw.res.conn.buf // conn's bufio writer + bw := cw.res.conn.bufw // conn's bufio writer // zero chunk to mark EOF bw.WriteString("0\r\n") if len(cw.res.trailers) > 0 { @@ -315,12 +308,12 @@ func (cw *chunkWriter) close() { type response struct { conn *conn req *Request // request for this response - wroteHeader bool // reply header has been (logically) written - wroteContinue bool // 100 Continue response was written + reqBody io.ReadCloser + wroteHeader bool // reply header has been (logically) written + wroteContinue bool // 100 Continue response was written w *bufio.Writer // buffers output in chunks to chunkWriter cw chunkWriter - sw *switchWriter // of the bufio.Writer, for return to putBufioWriter // handlerHeader is the Header that Handlers get access to, // which may be retained and mutated even after WriteHeader. @@ -354,13 +347,22 @@ type response struct { // written. trailers []string - handlerDone bool // set true when the handler exits + handlerDone atomicBool // set true when the handler exits // Buffers for Date and Content-Length dateBuf [len(TimeFormat)]byte clenBuf [10]byte + + // closeNotifyCh is non-nil once CloseNotify is called. + // Guarded by conn.mu + closeNotifyCh <-chan bool } +type atomicBool int32 + +func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 } +func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) } + // declareTrailer is called for each Trailer header when the // response header is written. It notes that a header will need to be // written in the trailers at the end of the response. @@ -423,7 +425,9 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) { return 0, err } if !ok || !regFile { - return io.Copy(writerOnly{w}, src) + bufp := copyBufPool.Get().(*[]byte) + defer copyBufPool.Put(bufp) + return io.CopyBuffer(writerOnly{w}, src, *bufp) } // sendfile path: @@ -456,29 +460,88 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) { return n, err } -// noLimit is an effective infinite upper bound for io.LimitedReader -const noLimit int64 = (1 << 63) - 1 - // debugServerConnections controls whether all server connections are wrapped // with a verbose logging wrapper. const debugServerConnections = false // Create new connection from rwc. -func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) { - c = new(conn) - c.remoteAddr = rwc.RemoteAddr().String() - c.server = srv - c.rwc = rwc - c.w = rwc +func (srv *Server) newConn(rwc net.Conn) *conn { + c := &conn{ + server: srv, + rwc: rwc, + } if debugServerConnections { c.rwc = newLoggingConn("server", c.rwc) } - c.sr.r = c.rwc - c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader) - br := newBufioReader(c.lr) - bw := newBufioWriterSize(checkConnErrorWriter{c}, 4<<10) - c.buf = bufio.NewReadWriter(br, bw) - return c, nil + return c +} + +type readResult struct { + n int + err error + b byte // byte read, if n == 1 +} + +// connReader is the io.Reader wrapper used by *conn. It combines a +// selectively-activated io.LimitedReader (to bound request header +// read sizes) with support for selectively keeping an io.Reader.Read +// call blocked in a background goroutine to wait for activity and +// trigger a CloseNotifier channel. +type connReader struct { + r io.Reader + remain int64 // bytes remaining + + // ch is non-nil if a background read is in progress. + // It is guarded by conn.mu. + ch chan readResult +} + +func (cr *connReader) setReadLimit(remain int64) { cr.remain = remain } +func (cr *connReader) setInfiniteReadLimit() { cr.remain = 1<<63 - 1 } +func (cr *connReader) hitReadLimit() bool { return cr.remain <= 0 } + +func (cr *connReader) Read(p []byte) (n int, err error) { + if cr.hitReadLimit() { + return 0, io.EOF + } + if len(p) == 0 { + return + } + if int64(len(p)) > cr.remain { + p = p[:cr.remain] + } + + // Is a background read (started by CloseNotifier) already in + // flight? If so, wait for it and use its result. + ch := cr.ch + if ch != nil { + cr.ch = nil + res := <-ch + if res.n == 1 { + p[0] = res.b + cr.remain -= 1 + } + return res.n, res.err + } + n, err = cr.r.Read(p) + cr.remain -= int64(n) + return +} + +func (cr *connReader) startBackgroundRead(onReadComplete func()) { + if cr.ch != nil { + // Background read already started. + return + } + cr.ch = make(chan readResult, 1) + go cr.closeNotifyAwaitActivityRead(cr.ch, onReadComplete) +} + +func (cr *connReader) closeNotifyAwaitActivityRead(ch chan<- readResult, onReadComplete func()) { + var buf [1]byte + n, err := cr.r.Read(buf[:1]) + onReadComplete() + ch <- readResult{n, err, buf[0]} } var ( @@ -487,6 +550,13 @@ var ( bufioWriter4kPool sync.Pool ) +var copyBufPool = sync.Pool{ + New: func() interface{} { + b := make([]byte, 32*1024) + return &b + }, +} + func bufioWriterPool(size int) *sync.Pool { switch size { case 2 << 10: @@ -544,7 +614,7 @@ func (srv *Server) maxHeaderBytes() int { return DefaultMaxHeaderBytes } -func (srv *Server) initialLimitedReaderSize() int64 { +func (srv *Server) initialReadLimitSize() int64 { return int64(srv.maxHeaderBytes()) + 4096 // bufio slop } @@ -563,8 +633,8 @@ func (ecr *expectContinueReader) Read(p []byte) (n int, err error) { } if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked() { ecr.resp.wroteContinue = true - ecr.resp.conn.buf.WriteString("HTTP/1.1 100 Continue\r\n\r\n") - ecr.resp.conn.buf.Flush() + ecr.resp.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n") + ecr.resp.conn.bufw.Flush() } n, err = ecr.readCloser.Read(p) if err == io.EOF { @@ -578,10 +648,12 @@ func (ecr *expectContinueReader) Close() error { return ecr.readCloser.Close() } -// TimeFormat is the time format to use with -// time.Parse and time.Time.Format when parsing -// or generating times in HTTP headers. -// It is like time.RFC1123 but hard codes GMT as the time zone. +// TimeFormat is the time format to use when generating times in HTTP +// headers. It is like time.RFC1123 but hard-codes GMT as the time +// zone. The time being formatted must be in UTC for Format to +// generate the correct format. +// +// For parsing this time format, see ParseTime. const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT" // appendTime is a non-allocating version of []byte(t.UTC().Format(TimeFormat)) @@ -623,21 +695,45 @@ func (c *conn) readRequest() (w *response, err error) { }() } - c.lr.N = c.server.initialLimitedReaderSize() + c.r.setReadLimit(c.server.initialReadLimitSize()) + c.mu.Lock() // while using bufr 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)) + peek, _ := c.bufr.Peek(4) // ReadRequest will get err below + c.bufr.Discard(numLeadingCRorLF(peek)) } - var req *Request - if req, err = ReadRequest(c.buf.Reader); err != nil { - if c.lr.N == 0 { + req, err := readRequest(c.bufr, keepHostHeader) + c.mu.Unlock() + if err != nil { + if c.r.hitReadLimit() { return nil, errTooLarge } return nil, err } - c.lr.N = noLimit c.lastMethod = req.Method + c.r.setInfiniteReadLimit() + + hosts, haveHost := req.Header["Host"] + if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) { + return nil, badRequestError("missing required Host header") + } + if len(hosts) > 1 { + return nil, badRequestError("too many Host headers") + } + if len(hosts) == 1 && !validHostHeader(hosts[0]) { + return nil, badRequestError("malformed Host header") + } + for k, vv := range req.Header { + if !validHeaderName(k) { + return nil, badRequestError("invalid header name") + } + for _, v := range vv { + if !validHeaderValue(v) { + return nil, badRequestError("invalid header value") + } + } + } + delete(req.Header, "Host") req.RemoteAddr = c.remoteAddr req.TLS = c.tlsState @@ -648,6 +744,7 @@ func (c *conn) readRequest() (w *response, err error) { w = &response{ conn: c, req: req, + reqBody: req.Body, handlerHeader: make(Header), contentLength: -1, } @@ -755,7 +852,7 @@ func (h extraHeader) Write(w *bufio.Writer) { } // writeHeader finalizes the header sent to the client and writes it -// to cw.res.conn.buf. +// to cw.res.conn.bufw. // // p is not written by writeHeader, but is the first chunk of the body // that will be written. It is sniffed for a Content-Type if none is @@ -821,7 +918,7 @@ func (cw *chunkWriter) writeHeader(p []byte) { // send a Content-Length header. // Further, we don't send an automatic Content-Length if they // set a Transfer-Encoding, because they're generally incompatible. - if w.handlerDone && !trailers && !hasTE && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) { + if w.handlerDone.isSet() && !trailers && !hasTE && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) { w.contentLength = int64(len(p)) setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10) } @@ -898,7 +995,7 @@ func (cw *chunkWriter) writeHeader(p []byte) { } if discard { - _, err := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1) + _, err := io.CopyN(ioutil.Discard, w.reqBody, maxPostHandlerReadBytes+1) switch err { case nil: // There must be even more data left over. @@ -907,7 +1004,7 @@ func (cw *chunkWriter) writeHeader(p []byte) { // Body was already consumed and closed. case io.EOF: // The remaining body was just consumed, close it. - err = w.req.Body.Close() + err = w.reqBody.Close() if err != nil { w.closeAfterReply = true } @@ -996,10 +1093,10 @@ func (cw *chunkWriter) writeHeader(p []byte) { } } - w.conn.buf.WriteString(statusLine(w.req, code)) - cw.header.WriteSubset(w.conn.buf, excludeHeader) - setHeader.Write(w.conn.buf.Writer) - w.conn.buf.Write(crlf) + w.conn.bufw.WriteString(statusLine(w.req, code)) + cw.header.WriteSubset(w.conn.bufw, excludeHeader) + setHeader.Write(w.conn.bufw) + w.conn.bufw.Write(crlf) } // foreachHeaderElement splits v according to the "#rule" construction @@ -1144,7 +1241,7 @@ func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err er } func (w *response) finishRequest() { - w.handlerDone = true + w.handlerDone.setTrue() if !w.wroteHeader { w.WriteHeader(StatusOK) @@ -1153,11 +1250,11 @@ func (w *response) finishRequest() { w.w.Flush() putBufioWriter(w.w) w.cw.close() - w.conn.buf.Flush() + w.conn.bufw.Flush() // Close the body (regardless of w.closeAfterReply) so we can // re-use its bufio.Reader later safely. - w.req.Body.Close() + w.reqBody.Close() if w.req.MultipartForm != nil { w.req.MultipartForm.RemoveAll() @@ -1206,28 +1303,26 @@ func (w *response) Flush() { } func (c *conn) finalFlush() { - if c.buf != nil { - c.buf.Flush() - + if c.bufr != nil { // Steal the bufio.Reader (~4KB worth of memory) and its associated // reader for a future connection. - putBufioReader(c.buf.Reader) + putBufioReader(c.bufr) + c.bufr = nil + } + if c.bufw != nil { + c.bufw.Flush() // Steal the bufio.Writer (~4KB worth of memory) and its associated // writer for a future connection. - putBufioWriter(c.buf.Writer) - - c.buf = nil + putBufioWriter(c.bufw) + c.bufw = nil } } // Close the connection. func (c *conn) close() { c.finalFlush() - if c.rwc != nil { - c.rwc.Close() - c.rwc = nil - } + c.rwc.Close() } // rstAvoidanceDelay is the amount of time we sleep after closing the @@ -1277,9 +1372,16 @@ func (c *conn) setState(nc net.Conn, state ConnState) { } } +// badRequestError is a literal string (used by in the server in HTML, +// unescaped) to tell the user why their request was bad. It should +// be plain text without user info or other embeddded errors. +type badRequestError string + +func (e badRequestError) Error() string { return "Bad Request: " + string(e) } + // Serve a new connection. func (c *conn) serve() { - origConn := c.rwc // copy it before it's set nil on Close or Hijack + c.remoteAddr = c.rwc.RemoteAddr().String() defer func() { if err := recover(); err != nil { const size = 64 << 10 @@ -1289,7 +1391,7 @@ func (c *conn) serve() { } if !c.hijacked() { c.close() - c.setState(origConn, StateClosed) + c.setState(c.rwc, StateClosed) } }() @@ -1315,9 +1417,13 @@ func (c *conn) serve() { } } + c.r = &connReader{r: c.rwc} + c.bufr = newBufioReader(c.r) + c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10) + for { w, err := c.readRequest() - if c.lr.N != c.server.initialLimitedReaderSize() { + if c.r.remain != c.server.initialReadLimitSize() { // If we read any bytes off the wire, we're active. c.setState(c.rwc, StateActive) } @@ -1328,16 +1434,22 @@ func (c *conn) serve() { // responding to them and hanging up // while they're still writing their // request. Undefined behavior. - io.WriteString(c.rwc, "HTTP/1.1 413 Request Entity Too Large\r\n\r\n") + io.WriteString(c.rwc, "HTTP/1.1 431 Request Header Fields Too Large\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n431 Request Header Fields Too Large") c.closeWriteAndWait() - break - } else if err == io.EOF { - break // Don't reply - } else if neterr, ok := err.(net.Error); ok && neterr.Timeout() { - break // Don't reply + return } - io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\n\r\n") - break + if err == io.EOF { + return // don't reply + } + if neterr, ok := err.(net.Error); ok && neterr.Timeout() { + return // don't reply + } + var publicErr string + if v, ok := err.(badRequestError); ok { + publicErr = ": " + string(v) + } + io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n400 Bad Request"+publicErr) + return } // Expect 100 Continue support @@ -1347,10 +1459,9 @@ func (c *conn) serve() { // Wrap the Body reader with one that replies on the connection req.Body = &expectContinueReader{readCloser: req.Body, resp: w} } - req.Header.Del("Expect") } else if req.Header.get("Expect") != "" { w.sendExpectationFailed() - break + return } // HTTP cannot have multiple simultaneous active requests.[*] @@ -1367,7 +1478,7 @@ func (c *conn) serve() { if w.requestBodyLimitHit || w.closedRequestBodyEarly() { c.closeWriteAndWait() } - break + return } c.setState(c.rwc, StateIdle) } @@ -1394,12 +1505,24 @@ func (w *response) sendExpectationFailed() { // Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter // and a Hijacker. func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) { + if w.handlerDone.isSet() { + panic("net/http: Hijack called after ServeHTTP finished") + } if w.wroteHeader { w.cw.flush() } + + c := w.conn + c.mu.Lock() + defer c.mu.Unlock() + + if w.closeNotifyCh != nil { + return nil, nil, errors.New("http: Hijack is incompatible with use of CloseNotifier in same ServeHTTP call") + } + // Release the bufioWriter that writes to the chunk writer, it is not // used after a connection has been hijacked. - rwc, buf, err = w.conn.hijack() + rwc, buf, err = c.hijackLocked() if err == nil { putBufioWriter(w.w) w.w = nil @@ -1408,13 +1531,86 @@ func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) { } func (w *response) CloseNotify() <-chan bool { - return w.conn.closeNotify() + if w.handlerDone.isSet() { + panic("net/http: CloseNotify called after ServeHTTP finished") + } + c := w.conn + c.mu.Lock() + defer c.mu.Unlock() + + if w.closeNotifyCh != nil { + return w.closeNotifyCh + } + ch := make(chan bool, 1) + w.closeNotifyCh = ch + + if w.conn.hijackedv { + // CloseNotify is undefined after a hijack, but we have + // no place to return an error, so just return a channel, + // even though it'll never receive a value. + return ch + } + + var once sync.Once + notify := func() { once.Do(func() { ch <- true }) } + + if requestBodyRemains(w.reqBody) { + // They're still consuming the request body, so we + // shouldn't notify yet. + registerOnHitEOF(w.reqBody, func() { + c.mu.Lock() + defer c.mu.Unlock() + startCloseNotifyBackgroundRead(c, notify) + }) + } else { + startCloseNotifyBackgroundRead(c, notify) + } + return ch +} + +// c.mu must be held. +func startCloseNotifyBackgroundRead(c *conn, notify func()) { + if c.bufr.Buffered() > 0 { + // They've consumed the request body, so anything + // remaining is a pipelined request, which we + // document as firing on. + notify() + } else { + c.r.startBackgroundRead(notify) + } +} + +func registerOnHitEOF(rc io.ReadCloser, fn func()) { + switch v := rc.(type) { + case *expectContinueReader: + registerOnHitEOF(v.readCloser, fn) + case *body: + v.registerOnHitEOF(fn) + default: + panic("unexpected type " + fmt.Sprintf("%T", rc)) + } +} + +// requestBodyRemains reports whether future calls to Read +// on rc might yield more data. +func requestBodyRemains(rc io.ReadCloser) bool { + if rc == eofReader { + return false + } + switch v := rc.(type) { + case *expectContinueReader: + return requestBodyRemains(v.readCloser) + case *body: + return v.bodyRemains() + default: + panic("unexpected type " + fmt.Sprintf("%T", rc)) + } } // The HandlerFunc type is an adapter to allow the use of // ordinary functions as HTTP handlers. If f is a function // with the appropriate signature, HandlerFunc(f) is a -// Handler object that calls f. +// Handler that calls f. type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). @@ -1461,6 +1657,9 @@ func StripPrefix(prefix string, h Handler) Handler { // Redirect replies to the request with a redirect to url, // which may be a path relative to the request path. +// +// The provided code should be in the 3xx range and is usually +// StatusMovedPermanently, StatusFound or StatusSeeOther. func Redirect(w ResponseWriter, r *Request, urlStr string, code int) { if u, err := url.Parse(urlStr); err == nil { // If url was relative, make absolute by @@ -1479,11 +1678,12 @@ func Redirect(w ResponseWriter, r *Request, urlStr string, code int) { // Because of this problem, no one pays attention // to the RFC; they all send back just a new path. // So do we. - oldpath := r.URL.Path - if oldpath == "" { // should not happen, but avoid a crash if it does - oldpath = "/" - } - if u.Scheme == "" { + if u.Scheme == "" && u.Host == "" { + oldpath := r.URL.Path + if oldpath == "" { // should not happen, but avoid a crash if it does + oldpath = "/" + } + // no leading http://server if urlStr == "" || urlStr[0] != '/' { // make relative path absolute @@ -1545,6 +1745,9 @@ func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) { // RedirectHandler returns a request handler that redirects // each request it receives to the given url using the given // status code. +// +// The provided code should be in the 3xx range and is usually +// StatusMovedPermanently, StatusFound or StatusSeeOther. func RedirectHandler(url string, code int) Handler { return &redirectHandler{url, code} } @@ -1567,6 +1770,14 @@ func RedirectHandler(url string, code int) Handler { // the pattern "/" matches all paths not matched by other registered // patterns, not just the URL with Path == "/". // +// If a subtree has been registered and a request is received naming the +// subtree root without its trailing slash, ServeMux redirects that +// request to the subtree root (adding the trailing slash). This behavior can +// be overridden with a separate registration for the path without +// the trailing slash. For example, registering "/images/" causes ServeMux +// to redirect a request for "/images" to "/images/", unless "/images" has +// been registered separately. +// // Patterns may optionally begin with a host name, restricting matches to // URLs on that host only. Host-specific patterns take precedence over // general patterns, so that a handler might register for the two patterns @@ -1574,8 +1785,8 @@ func RedirectHandler(url string, code int) Handler { // requests for "http://www.google.com/". // // ServeMux also takes care of sanitizing the URL request path, -// redirecting any request containing . or .. elements to an -// equivalent .- and ..-free URL. +// redirecting any request containing . or .. elements or repeated slashes +// to an equivalent, cleaner URL. type ServeMux struct { mu sync.RWMutex m map[string]muxEntry @@ -1782,6 +1993,7 @@ type Server struct { // handle HTTP requests and will initialize the Request's TLS // and RemoteAddr if not already set. The connection is // automatically closed when the function returns. + // If TLSNextProto is nil, HTTP/2 support is enabled automatically. TLSNextProto map[string]func(*Server, *tls.Conn, Handler) // ConnState specifies an optional callback function that is @@ -1795,7 +2007,9 @@ type Server struct { // standard logger. ErrorLog *log.Logger - disableKeepAlives int32 // accessed atomically. + disableKeepAlives int32 // accessed atomically. + nextProtoOnce sync.Once // guards initialization of TLSNextProto in Serve + nextProtoErr error } // A ConnState represents the state of a client connection to a server. @@ -1815,6 +2029,11 @@ const ( // and doesn't fire again until the request has been // handled. After the request is handled, the state // transitions to StateClosed, StateHijacked, or StateIdle. + // For HTTP/2, StateActive fires on the transition from zero + // to one active request, and only transitions away once all + // active requests are complete. That means that ConnState + // can not be used to do per-request work; ConnState only notes + // the overall state of the connection. StateActive // StateIdle represents a connection that has finished @@ -1863,8 +2082,10 @@ func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { } // ListenAndServe listens on the TCP network address srv.Addr and then -// calls Serve to handle requests on incoming connections. If -// srv.Addr is blank, ":http" is used. +// calls Serve to handle requests on incoming connections. +// Accepted connections are configured to enable TCP keep-alives. +// If srv.Addr is blank, ":http" is used. +// ListenAndServe always returns a non-nil error. func (srv *Server) ListenAndServe() error { addr := srv.Addr if addr == "" { @@ -1877,12 +2098,21 @@ func (srv *Server) ListenAndServe() error { return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) } +var testHookServerServe func(*Server, net.Listener) // used if non-nil + // Serve accepts incoming connections on the Listener l, creating a -// new service goroutine for each. The service goroutines read requests and +// new service goroutine for each. The service goroutines read requests and // then call srv.Handler to reply to them. +// Serve always returns a non-nil error. func (srv *Server) Serve(l net.Listener) error { defer l.Close() + if fn := testHookServerServe; fn != nil { + fn(srv, l) + } var tempDelay time.Duration // how long to sleep on accept failure + if err := srv.setupHTTP2(); err != nil { + return err + } for { rw, e := l.Accept() if e != nil { @@ -1902,10 +2132,7 @@ func (srv *Server) Serve(l net.Listener) error { return e } tempDelay = 0 - c, err := srv.newConn(rw) - if err != nil { - continue - } + c := srv.newConn(rw) c.setState(c.rwc, StateNew) // before Serve can return go c.serve() } @@ -1937,8 +2164,10 @@ func (s *Server) logf(format string, args ...interface{}) { // ListenAndServe listens on the TCP network address addr // and then calls Serve with handler to handle requests -// on incoming connections. Handler is typically nil, -// in which case the DefaultServeMux is used. +// on incoming connections. +// Accepted connections are configured to enable TCP keep-alives. +// Handler is typically nil, in which case the DefaultServeMux is +// used. // // A trivial example server is: // @@ -1957,11 +2186,10 @@ func (s *Server) logf(format string, args ...interface{}) { // // func main() { // http.HandleFunc("/hello", HelloServer) -// err := http.ListenAndServe(":12345", nil) -// if err != nil { -// log.Fatal("ListenAndServe: ", err) -// } +// log.Fatal(http.ListenAndServe(":12345", nil)) // } +// +// ListenAndServe always returns a non-nil error. func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() @@ -1989,19 +2217,20 @@ func ListenAndServe(addr string, handler Handler) error { // http.HandleFunc("/", handler) // log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/") // err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil) -// if err != nil { -// log.Fatal(err) -// } +// log.Fatal(err) // } // // One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem. -func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error { +// +// ListenAndServeTLS always returns a non-nil error. +func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServeTLS(certFile, keyFile) } // ListenAndServeTLS listens on the TCP network address srv.Addr and // then calls Serve to handle requests on incoming TLS connections. +// Accepted connections are configured to enable TCP keep-alives. // // Filenames containing a certificate and matching private key for the // server must be provided if the Server's TLSConfig.Certificates is @@ -2010,14 +2239,23 @@ func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Han // certificate, any intermediates, and the CA's certificate. // // If srv.Addr is blank, ":https" is used. +// +// ListenAndServeTLS always returns a non-nil error. func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { addr := srv.Addr if addr == "" { addr = ":https" } + + // Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig + // before we clone it and create the TLS Listener. + if err := srv.setupHTTP2(); err != nil { + return err + } + config := cloneTLSConfig(srv.TLSConfig) - if config.NextProtos == nil { - config.NextProtos = []string{"http/1.1"} + if !strSliceContains(config.NextProtos, "http/1.1") { + config.NextProtos = append(config.NextProtos, "http/1.1") } if len(config.Certificates) == 0 || certFile != "" || keyFile != "" { @@ -2038,6 +2276,25 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { return srv.Serve(tlsListener) } +func (srv *Server) setupHTTP2() error { + srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults) + return srv.nextProtoErr +} + +// onceSetNextProtoDefaults configures HTTP/2, if the user hasn't +// configured otherwise. (by setting srv.TLSNextProto non-nil) +// It must only be called via srv.nextProtoOnce (use srv.setupHTTP2). +func (srv *Server) onceSetNextProtoDefaults() { + if strings.Contains(os.Getenv("GODEBUG"), "http2server=0") { + return + } + // Enable HTTP/2 by default if the user hasn't otherwise + // configured their TLSNextProto map. + if srv.TLSNextProto == nil { + srv.nextProtoErr = http2ConfigureServer(srv, nil) + } +} + // TimeoutHandler returns a Handler that runs h with the given time limit. // // The new Handler calls h.ServeHTTP to handle each request, but if a @@ -2046,11 +2303,20 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { // (If msg is empty, a suitable default message will be sent.) // After such a timeout, writes by h to its ResponseWriter will return // ErrHandlerTimeout. +// +// TimeoutHandler buffers all Handler writes to memory and does not +// support the Hijacker or Flusher interfaces. func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler { - f := func() <-chan time.Time { - return time.After(dt) + t := time.NewTimer(dt) + return &timeoutHandler{ + handler: h, + body: msg, + + // Effectively storing a *time.Timer, but decomposed + // for testing: + timeout: func() <-chan time.Time { return t.C }, + cancelTimer: t.Stop, } - return &timeoutHandler{h, f, msg} } // ErrHandlerTimeout is returned on ResponseWriter Write calls @@ -2059,8 +2325,13 @@ var ErrHandlerTimeout = errors.New("http: Handler timeout") type timeoutHandler struct { handler Handler - timeout func() <-chan time.Time // returns channel producing a timeout body string + + // timeout returns the channel of a *time.Timer and + // cancelTimer cancels it. They're stored separately for + // testing purposes. + timeout func() <-chan time.Time // returns channel producing a timeout + cancelTimer func() bool // optional } func (h *timeoutHandler) errorBody() string { @@ -2071,46 +2342,61 @@ func (h *timeoutHandler) errorBody() string { } func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) { - done := make(chan bool, 1) - tw := &timeoutWriter{w: w} + done := make(chan struct{}) + tw := &timeoutWriter{ + w: w, + h: make(Header), + } go func() { h.handler.ServeHTTP(tw, r) - done <- true + close(done) }() select { case <-done: - return - case <-h.timeout(): tw.mu.Lock() defer tw.mu.Unlock() - if !tw.wroteHeader { - tw.w.WriteHeader(StatusServiceUnavailable) - tw.w.Write([]byte(h.errorBody())) + dst := w.Header() + for k, vv := range tw.h { + dst[k] = vv + } + w.WriteHeader(tw.code) + w.Write(tw.wbuf.Bytes()) + if h.cancelTimer != nil { + h.cancelTimer() } + case <-h.timeout(): + tw.mu.Lock() + defer tw.mu.Unlock() + w.WriteHeader(StatusServiceUnavailable) + io.WriteString(w, h.errorBody()) tw.timedOut = true + return } } type timeoutWriter struct { - w ResponseWriter + w ResponseWriter + h Header + wbuf bytes.Buffer mu sync.Mutex timedOut bool wroteHeader bool + code int } -func (tw *timeoutWriter) Header() Header { - return tw.w.Header() -} +func (tw *timeoutWriter) Header() Header { return tw.h } func (tw *timeoutWriter) Write(p []byte) (int, error) { tw.mu.Lock() defer tw.mu.Unlock() - tw.wroteHeader = true // implicitly at least if tw.timedOut { return 0, ErrHandlerTimeout } - return tw.w.Write(p) + if !tw.wroteHeader { + tw.writeHeader(StatusOK) + } + return tw.wbuf.Write(p) } func (tw *timeoutWriter) WriteHeader(code int) { @@ -2119,8 +2405,12 @@ func (tw *timeoutWriter) WriteHeader(code int) { if tw.timedOut || tw.wroteHeader { return } + tw.writeHeader(code) +} + +func (tw *timeoutWriter) writeHeader(code int) { tw.wroteHeader = true - tw.w.WriteHeader(code) + tw.code = code } // tcpKeepAliveListener sets TCP keep-alive timeouts on accepted @@ -2247,7 +2537,7 @@ type checkConnErrorWriter struct { } func (w checkConnErrorWriter) Write(p []byte) (n int, err error) { - n, err = w.c.w.Write(p) // c.w == c.rwc, except after a hijack, when rwc is nil. + n, err = w.c.rwc.Write(p) if err != nil && w.c.werr == nil { w.c.werr = err } @@ -2265,3 +2555,12 @@ func numLeadingCRorLF(v []byte) (n int) { return } + +func strSliceContains(ss []string, s string) bool { + for _, v := range ss { + if v == s { + return true + } + } + return false +} |