// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // HTTP server. See RFC 7230 through 7235. package http import ( "bufio" "bytes" "context" "crypto/tls" "errors" "fmt" "internal/godebug" "io" "log" "maps" "math/rand" "net" "net/textproto" "net/url" urlpkg "net/url" "path" "runtime" "slices" "strconv" "strings" "sync" "sync/atomic" "time" _ "unsafe" // for linkname "golang.org/x/net/http/httpguts" ) // Errors used by the HTTP server. var ( // ErrBodyNotAllowed is returned by ResponseWriter.Write calls // when the HTTP method or response code does not permit a // body. ErrBodyNotAllowed = errors.New("http: request method or response status code does not allow body") // ErrHijacked is returned by ResponseWriter.Write calls when // the underlying connection has been hijacked using the // Hijacker interface. A zero-byte write on a hijacked // connection will return ErrHijacked without any other side // effects. ErrHijacked = errors.New("http: connection has been hijacked") // ErrContentLength is returned by ResponseWriter.Write calls // when a Handler set a Content-Length response header with a // declared size and then attempted to write more bytes than // declared. ErrContentLength = errors.New("http: wrote more than the declared Content-Length") // Deprecated: ErrWriteAfterFlush is no longer returned by // anything in the net/http package. Callers should not // compare errors against this variable. ErrWriteAfterFlush = errors.New("unused") ) // A Handler responds to an HTTP request. // // [Handler.ServeHTTP] should write reply headers and data to the [ResponseWriter] // 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. // // Except for reading the body, handlers should not modify the // provided Request. // // 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 either closes the network connection or sends an HTTP/2 // RST_STREAM, depending on the HTTP protocol. To abort a handler so // the client sees an interrupted response but the server doesn't log // an error, panic with the value [ErrAbortHandler]. 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 [Handler.ServeHTTP] has returned. type ResponseWriter interface { // Header returns the header map that will be sent by // [ResponseWriter.WriteHeader]. The [Header] map also is the mechanism with which // [Handler] implementations can set HTTP trailers. // // Changing the header map after a call to [ResponseWriter.WriteHeader] (or // [ResponseWriter.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 // send by setting the "Trailer" header to the names of the // trailer keys which will come later. In this case, those // keys of the Header map are treated as if they were // trailers. See the example. The second way, for trailer // keys not known to the [Handler] until after the first [ResponseWriter.Write], // is to prefix the [Header] map keys with the [TrailerPrefix] // constant value. // // To suppress automatic response headers (such as "Date"), set // their value to nil. Header() Header // Write writes the data to the connection as part of an HTTP reply. // // If [ResponseWriter.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]. Additionally, if the total size of all written // data is under a few KB and there are no Flush calls, the // Content-Length header is added automatically. // // 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 the provided // status code. // // 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 or 1xx informational responses. // // The provided code must be a valid HTTP 1xx-5xx status code. // 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) } // The Flusher interface is implemented by ResponseWriters that allow // an HTTP handler to flush buffered data to the client. // // The default HTTP/1.x and HTTP/2 [ResponseWriter] implementations // support [Flusher], but ResponseWriter wrappers may not. Handlers // should always test for this ability at runtime. // // Note that even for ResponseWriters that support Flush, // if the client is connected through an HTTP proxy, // the buffered data may not reach the client until the response // completes. type Flusher interface { // Flush sends any buffered data to the client. Flush() } // The Hijacker interface is implemented by ResponseWriters that allow // an HTTP handler to take over the connection. // // The default [ResponseWriter] for HTTP/1.x connections supports // Hijacker, but HTTP/2 connections intentionally do not. // ResponseWriter wrappers may also not support Hijacker. Handlers // should always test for this ability at runtime. type Hijacker interface { // Hijack lets the caller take over the connection. // After a call to Hijack the HTTP server library // will not do anything else with the connection. // // It becomes the caller's responsibility to manage // and close the connection. // // The returned net.Conn may have read or write deadlines // already set, depending on the configuration of the // Server. It is the caller's responsibility to set // or clear those deadlines as needed. // // The returned bufio.Reader may contain unprocessed buffered // data from the client. // // After a call to Hijack, the original Request.Body must not // be used. The original Request's Context remains valid and // is not canceled until the Request's ServeHTTP method // returns. Hijack() (net.Conn, *bufio.ReadWriter, error) } // The CloseNotifier interface is implemented by ResponseWriters which // allow detecting when the underlying connection has gone away. // // This mechanism can be used to cancel long operations on the server // if the client has disconnected before the response is ready. // // Deprecated: the CloseNotifier interface predates Go's context package. // New code should use [Request.Context] instead. type CloseNotifier interface { // 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 as 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 } var ( // ServerContextKey is a context key. It can be used in HTTP // handlers with Context.Value to access the server that // started the handler. The associated value will be of // type *Server. ServerContextKey = &contextKey{"http-server"} // LocalAddrContextKey is a context key. It can be used in // HTTP handlers with Context.Value to access the local // address the connection arrived on. // The associated value will be of type net.Addr. LocalAddrContextKey = &contextKey{"local-addr"} ) // A conn represents the server side of an HTTP connection. type conn struct { // server is the server on which the connection arrived. // Immutable; never nil. server *Server // cancelCtx cancels the connection-level context. cancelCtx context.CancelFunc // 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. 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 curReq atomic.Pointer[response] // (which has a Request in it) curState atomic.Uint64 // packed (unixtime<<8|uint8(ConnState)) // mu guards hijackedv 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 { c.mu.Lock() defer c.mu.Unlock() return c.hijackedv } // c.mu must be held. func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) { if c.hijackedv { return nil, nil, ErrHijacked } c.r.abortPendingRead() c.hijackedv = true rwc = c.rwc rwc.SetDeadline(time.Time{}) buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc)) if c.r.hasByte { if _, err := c.bufr.Peek(c.bufr.Buffered() + 1); err != nil { return nil, nil, fmt.Errorf("unexpected Peek failure reading buffered byte: %v", err) } } c.setState(rwc, StateHijacked, runHooks) return } // This should be >= 512 bytes for DetectContentType, // but otherwise it's somewhat arbitrary. const bufferBeforeChunkingSize = 2048 // chunkWriter writes to a response's conn buffer, and is the writer // wrapped by the response.w buffered writer. // // chunkWriter also is responsible for finalizing the Header, including // conditionally setting the Content-Type and setting a Content-Length // in cases where the handler's final output is smaller than the buffer // size. It also conditionally adds chunk headers, when in chunking mode. // // See the comment above (*response).Write for the entire write flow. type chunkWriter struct { res *response // header is either nil or a deep clone of res.handlerHeader // at the time of res.writeHeader, if res.writeHeader is // called and extra buffering is being done to calculate // Content-Type and/or Content-Length. header Header // wroteHeader tells whether the header's been written to "the // wire" (or rather: w.conn.buf). this is unlike // (*response).wroteHeader, which tells only whether it was // logically written. wroteHeader bool // set by the writeHeader method: chunking bool // using chunked transfer encoding for reply body } var ( crlf = []byte("\r\n") colonSpace = []byte(": ") ) func (cw *chunkWriter) Write(p []byte) (n int, err error) { if !cw.wroteHeader { cw.writeHeader(p) } if cw.res.req.Method == "HEAD" { // Eat writes. return len(p), nil } if cw.chunking { _, 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.bufw.Write(p) if cw.chunking && err == nil { _, err = cw.res.conn.bufw.Write(crlf) } if err != nil { cw.res.conn.rwc.Close() } return } func (cw *chunkWriter) flush() error { if !cw.wroteHeader { cw.writeHeader(nil) } return cw.res.conn.bufw.Flush() } func (cw *chunkWriter) close() { if !cw.wroteHeader { cw.writeHeader(nil) } if cw.chunking { bw := cw.res.conn.bufw // conn's bufio writer // zero chunk to mark EOF bw.WriteString("0\r\n") if trailers := cw.res.finalTrailers(); trailers != nil { trailers.Write(bw) // the writer handles noting errors } // final blank line after the trailers (whether // present or not) bw.WriteString("\r\n") } } // A response represents the server side of an HTTP response. type response struct { conn *conn req *Request // request for this response reqBody io.ReadCloser cancelCtx context.CancelFunc // when ServeHTTP exits wroteHeader bool // a non-1xx header has been (logically) written wants10KeepAlive bool // HTTP/1.0 w/ Connection "keep-alive" wantsClose bool // HTTP request has Connection "close" // canWriteContinue is an atomic boolean that says whether or // not a 100 Continue header can be written to the // connection. // writeContinueMu must be held while writing the header. // These two fields together synchronize the body reader (the // expectContinueReader, which wants to write 100 Continue) // against the main writer. writeContinueMu sync.Mutex canWriteContinue atomic.Bool w *bufio.Writer // buffers output in chunks to chunkWriter cw chunkWriter // handlerHeader is the Header that Handlers get access to, // which may be retained and mutated even after WriteHeader. // handlerHeader is copied into cw.header at WriteHeader // time, and privately mutated thereafter. handlerHeader Header calledHeader bool // handler accessed handlerHeader via Header written int64 // number of bytes written in body contentLength int64 // explicitly-declared Content-Length; or -1 status int // status code passed to WriteHeader // close connection after this reply. set on request and // updated after response from handler if there's a // "Connection: keep-alive" response header and a // Content-Length. closeAfterReply bool // When fullDuplex is false (the default), we consume any remaining // request body before starting to write a response. fullDuplex bool // requestBodyLimitHit is set by requestTooLarge when // maxBytesReader hits its max size. It is checked in // WriteHeader, to make sure we don't consume the // remaining request body to try to advance to the next HTTP // request. Instead, when this is set, we stop reading // subsequent requests on this connection and stop reading // input from it. requestBodyLimitHit bool // trailers are the headers to be sent after the handler // finishes writing the body. This field is initialized from // the Trailer response header when the response header is // written. trailers []string handlerDone atomic.Bool // set true when the handler exits // Buffers for Date, Content-Length, and status code dateBuf [len(TimeFormat)]byte clenBuf [10]byte statusBuf [3]byte // closeNotifyCh is the channel returned by CloseNotify. // TODO(bradfitz): this is currently (for Go 1.8) always // non-nil. Make this lazily-created again as it used to be? closeNotifyCh chan bool didCloseNotify atomic.Bool // atomic (only false->true winner should send) } func (c *response) SetReadDeadline(deadline time.Time) error { return c.conn.rwc.SetReadDeadline(deadline) } func (c *response) SetWriteDeadline(deadline time.Time) error { return c.conn.rwc.SetWriteDeadline(deadline) } func (c *response) EnableFullDuplex() error { c.fullDuplex = true return nil } // TrailerPrefix is a magic prefix for [ResponseWriter.Header] map keys // that, if present, signals that the map entry is actually for // the response trailers, and not the response headers. The prefix // is stripped after the ServeHTTP call finishes and the values are // sent in the trailers. // // This mechanism is intended only for trailers that are not known // prior to the headers being written. If the set of trailers is fixed // or known before the header is written, the normal Go trailers mechanism // is preferred: // // https://pkg.go.dev/net/http#ResponseWriter // https://pkg.go.dev/net/http#example-ResponseWriter-Trailers const TrailerPrefix = "Trailer:" // finalTrailers is called after the Handler exits and returns a non-nil // value if the Handler set any trailers. func (w *response) finalTrailers() Header { var t Header for k, vv := range w.handlerHeader { if kk, found := strings.CutPrefix(k, TrailerPrefix); found { if t == nil { t = make(Header) } t[kk] = vv } } for _, k := range w.trailers { if t == nil { t = make(Header) } for _, v := range w.handlerHeader[k] { t.Add(k, v) } } return t } // 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. func (w *response) declareTrailer(k string) { k = CanonicalHeaderKey(k) if !httpguts.ValidTrailerHeader(k) { // Forbidden by RFC 7230, section 4.1.2 return } w.trailers = append(w.trailers, k) } // requestTooLarge is called by maxBytesReader when too much input has // been read from the client. func (w *response) requestTooLarge() { w.closeAfterReply = true w.requestBodyLimitHit = true if !w.wroteHeader { w.Header().Set("Connection", "close") } } // disableWriteContinue stops Request.Body.Read from sending an automatic 100-Continue. // If a 100-Continue is being written, it waits for it to complete before continuing. func (w *response) disableWriteContinue() { w.writeContinueMu.Lock() w.canWriteContinue.Store(false) w.writeContinueMu.Unlock() } // writerOnly hides an io.Writer value's optional ReadFrom method // from io.Copy. type writerOnly struct { io.Writer } // ReadFrom is here to optimize copying from an [*os.File] regular file // to a [*net.TCPConn] with sendfile, or from a supported src type such // as a *net.TCPConn on Linux with splice. func (w *response) ReadFrom(src io.Reader) (n int64, err error) { buf := getCopyBuf() defer putCopyBuf(buf) // Our underlying w.conn.rwc is usually a *TCPConn (with its // own ReadFrom method). If not, just fall back to the normal // copy method. rf, ok := w.conn.rwc.(io.ReaderFrom) if !ok { return io.CopyBuffer(writerOnly{w}, src, buf) } // Copy the first sniffLen bytes before switching to ReadFrom. // This ensures we don't start writing the response before the // source is available (see golang.org/issue/5660) and provides // enough bytes to perform Content-Type sniffing when required. if !w.cw.wroteHeader { n0, err := io.CopyBuffer(writerOnly{w}, io.LimitReader(src, sniffLen), buf) n += n0 if err != nil || n0 < sniffLen { return n, err } } w.w.Flush() // get rid of any previous writes w.cw.flush() // make sure Header is written; flush data to rwc // Now that cw has been flushed, its chunking field is guaranteed initialized. if !w.cw.chunking && w.bodyAllowed() { n0, err := rf.ReadFrom(src) n += n0 w.written += n0 return n, err } n0, err := io.CopyBuffer(writerOnly{w}, src, buf) n += n0 return n, err } // 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) *conn { c := &conn{ server: srv, rwc: rwc, } if debugServerConnections { c.rwc = newLoggingConn("server", c.rwc) } return c } type readResult struct { _ incomparable 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 { conn *conn mu sync.Mutex // guards following hasByte bool byteBuf [1]byte cond *sync.Cond inRead bool aborted bool // set true before conn.rwc deadline is set to past remain int64 // bytes remaining } func (cr *connReader) lock() { cr.mu.Lock() if cr.cond == nil { cr.cond = sync.NewCond(&cr.mu) } } func (cr *connReader) unlock() { cr.mu.Unlock() } func (cr *connReader) startBackgroundRead() { cr.lock() defer cr.unlock() if cr.inRead { panic("invalid concurrent Body.Read call") } if cr.hasByte { return } cr.inRead = true cr.conn.rwc.SetReadDeadline(time.Time{}) go cr.backgroundRead() } func (cr *connReader) backgroundRead() { n, err := cr.conn.rwc.Read(cr.byteBuf[:]) cr.lock() if n == 1 { cr.hasByte = true // We were past the end of the previous request's body already // (since we wouldn't be in a background read otherwise), so // this is a pipelined HTTP request. Prior to Go 1.11 we used to // send on the CloseNotify channel and cancel the context here, // but the behavior was documented as only "may", and we only // did that because that's how CloseNotify accidentally behaved // in very early Go releases prior to context support. Once we // added context support, people used a Handler's // Request.Context() and passed it along. Having that context // cancel on pipelined HTTP requests caused problems. // Fortunately, almost nothing uses HTTP/1.x pipelining. // Unfortunately, apt-get does, or sometimes does. // New Go 1.11 behavior: don't fire CloseNotify or cancel // contexts on pipelined requests. Shouldn't affect people, but // fixes cases like Issue 23921. This does mean that a client // closing their TCP connection after sending a pipelined // request won't cancel the context, but we'll catch that on any // write failure (in checkConnErrorWriter.Write). // If the server never writes, yes, there are still contrived // server & client behaviors where this fails to ever cancel the // context, but that's kinda why HTTP/1.x pipelining died // anyway. } if ne, ok := err.(net.Error); ok && cr.aborted && ne.Timeout() { // Ignore this error. It's the expected error from // another goroutine calling abortPendingRead. } else if err != nil { cr.handleReadError(err) } cr.aborted = false cr.inRead = false cr.unlock() cr.cond.Broadcast() } func (cr *connReader) abortPendingRead() { cr.lock() defer cr.unlock() if !cr.inRead { return } cr.aborted = true cr.conn.rwc.SetReadDeadline(aLongTimeAgo) for cr.inRead { cr.cond.Wait() } cr.conn.rwc.SetReadDeadline(time.Time{}) } func (cr *connReader) setReadLimit(remain int64) { cr.remain = remain } func (cr *connReader) setInfiniteReadLimit() { cr.remain = maxInt64 } func (cr *connReader) hitReadLimit() bool { return cr.remain <= 0 } // handleReadError is called whenever a Read from the client returns a // non-nil error. // // The provided non-nil err is almost always io.EOF or a "use of // closed network connection". In any case, the error is not // particularly interesting, except perhaps for debugging during // development. Any error means the connection is dead and we should // down its context. // // It may be called from multiple goroutines. func (cr *connReader) handleReadError(_ error) { cr.conn.cancelCtx() cr.closeNotify() } // may be called from multiple goroutines. func (cr *connReader) closeNotify() { res := cr.conn.curReq.Load() if res != nil && !res.didCloseNotify.Swap(true) { res.closeNotifyCh <- true } } func (cr *connReader) Read(p []byte) (n int, err error) { cr.lock() if cr.inRead { cr.unlock() if cr.conn.hijacked() { panic("invalid Body.Read call. After hijacked, the original Request must not be used") } panic("invalid concurrent Body.Read call") } if cr.hitReadLimit() { cr.unlock() return 0, io.EOF } if len(p) == 0 { cr.unlock() return 0, nil } if int64(len(p)) > cr.remain { p = p[:cr.remain] } if cr.hasByte { p[0] = cr.byteBuf[0] cr.hasByte = false cr.unlock() return 1, nil } cr.inRead = true cr.unlock() n, err = cr.conn.rwc.Read(p) cr.lock() cr.inRead = false if err != nil { cr.handleReadError(err) } cr.remain -= int64(n) cr.unlock() cr.cond.Broadcast() return n, err } var ( bufioReaderPool sync.Pool bufioWriter2kPool sync.Pool bufioWriter4kPool sync.Pool ) const copyBufPoolSize = 32 * 1024 var copyBufPool = sync.Pool{New: func() any { return new([copyBufPoolSize]byte) }} func getCopyBuf() []byte { return copyBufPool.Get().(*[copyBufPoolSize]byte)[:] } func putCopyBuf(b []byte) { if len(b) != copyBufPoolSize { panic("trying to put back buffer of the wrong size in the copyBufPool") } copyBufPool.Put((*[copyBufPoolSize]byte)(b)) } func bufioWriterPool(size int) *sync.Pool { switch size { case 2 << 10: return &bufioWriter2kPool case 4 << 10: return &bufioWriter4kPool } return nil } // newBufioReader should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/gobwas/ws // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname newBufioReader func newBufioReader(r io.Reader) *bufio.Reader { if v := bufioReaderPool.Get(); v != nil { br := v.(*bufio.Reader) br.Reset(r) return br } // Note: if this reader size is ever changed, update // TestHandlerBodyClose's assumptions. return bufio.NewReader(r) } // putBufioReader should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/gobwas/ws // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname putBufioReader func putBufioReader(br *bufio.Reader) { br.Reset(nil) bufioReaderPool.Put(br) } // newBufioWriterSize should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/gobwas/ws // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname newBufioWriterSize func newBufioWriterSize(w io.Writer, size int) *bufio.Writer { pool := bufioWriterPool(size) if pool != nil { if v := pool.Get(); v != nil { bw := v.(*bufio.Writer) bw.Reset(w) return bw } } return bufio.NewWriterSize(w, size) } // putBufioWriter should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/gobwas/ws // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname putBufioWriter func putBufioWriter(bw *bufio.Writer) { bw.Reset(nil) if pool := bufioWriterPool(bw.Available()); pool != nil { pool.Put(bw) } } // DefaultMaxHeaderBytes is the maximum permitted size of the headers // in an HTTP request. // This can be overridden by setting [Server.MaxHeaderBytes]. const DefaultMaxHeaderBytes = 1 << 20 // 1 MB func (srv *Server) maxHeaderBytes() int { if srv.MaxHeaderBytes > 0 { return srv.MaxHeaderBytes } return DefaultMaxHeaderBytes } func (srv *Server) initialReadLimitSize() int64 { return int64(srv.maxHeaderBytes()) + 4096 // bufio slop } // tlsHandshakeTimeout returns the time limit permitted for the TLS // handshake, or zero for unlimited. // // It returns the minimum of any positive ReadHeaderTimeout, // ReadTimeout, or WriteTimeout. func (srv *Server) tlsHandshakeTimeout() time.Duration { var ret time.Duration for _, v := range [...]time.Duration{ srv.ReadHeaderTimeout, srv.ReadTimeout, srv.WriteTimeout, } { if v <= 0 { continue } if ret == 0 || v < ret { ret = v } } return ret } // wrapper around io.ReadCloser which on first read, sends an // HTTP/1.1 100 Continue header type expectContinueReader struct { resp *response readCloser io.ReadCloser closed atomic.Bool sawEOF atomic.Bool } func (ecr *expectContinueReader) Read(p []byte) (n int, err error) { if ecr.closed.Load() { return 0, ErrBodyReadAfterClose } w := ecr.resp if w.canWriteContinue.Load() { w.writeContinueMu.Lock() if w.canWriteContinue.Load() { w.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n") w.conn.bufw.Flush() w.canWriteContinue.Store(false) } w.writeContinueMu.Unlock() } n, err = ecr.readCloser.Read(p) if err == io.EOF { ecr.sawEOF.Store(true) } return } func (ecr *expectContinueReader) Close() error { ecr.closed.Store(true) return ecr.readCloser.Close() } // 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)) func appendTime(b []byte, t time.Time) []byte { const days = "SunMonTueWedThuFriSat" const months = "JanFebMarAprMayJunJulAugSepOctNovDec" t = t.UTC() yy, mm, dd := t.Date() hh, mn, ss := t.Clock() day := days[3*t.Weekday():] mon := months[3*(mm-1):] return append(b, day[0], day[1], day[2], ',', ' ', byte('0'+dd/10), byte('0'+dd%10), ' ', mon[0], mon[1], mon[2], ' ', byte('0'+yy/1000), byte('0'+(yy/100)%10), byte('0'+(yy/10)%10), byte('0'+yy%10), ' ', byte('0'+hh/10), byte('0'+hh%10), ':', byte('0'+mn/10), byte('0'+mn%10), ':', byte('0'+ss/10), byte('0'+ss%10), ' ', 'G', 'M', 'T') } var errTooLarge = errors.New("http: request too large") // Read next request from connection. func (c *conn) readRequest(ctx context.Context) (w *response, err error) { if c.hijacked() { return nil, ErrHijacked } var ( wholeReqDeadline time.Time // or zero if none hdrDeadline time.Time // or zero if none ) t0 := time.Now() if d := c.server.readHeaderTimeout(); d > 0 { hdrDeadline = t0.Add(d) } if d := c.server.ReadTimeout; d > 0 { wholeReqDeadline = t0.Add(d) } c.rwc.SetReadDeadline(hdrDeadline) if d := c.server.WriteTimeout; d > 0 { defer func() { c.rwc.SetWriteDeadline(time.Now().Add(d)) }() } c.r.setReadLimit(c.server.initialReadLimitSize()) if c.lastMethod == "POST" { // RFC 7230 section 3 tolerance for old buggy clients. peek, _ := c.bufr.Peek(4) // ReadRequest will get err below c.bufr.Discard(numLeadingCRorLF(peek)) } req, err := readRequest(c.bufr) if err != nil { if c.r.hitReadLimit() { return nil, errTooLarge } return nil, err } if !http1ServerSupportsRequest(req) { return nil, statusError{StatusHTTPVersionNotSupported, "unsupported protocol version"} } c.lastMethod = req.Method c.r.setInfiniteReadLimit() hosts, haveHost := req.Header["Host"] isH2Upgrade := req.isH2Upgrade() if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) && !isH2Upgrade && req.Method != "CONNECT" { return nil, badRequestError("missing required Host header") } if len(hosts) == 1 && !httpguts.ValidHostHeader(hosts[0]) { return nil, badRequestError("malformed Host header") } for k, vv := range req.Header { if !httpguts.ValidHeaderFieldName(k) { return nil, badRequestError("invalid header name") } for _, v := range vv { if !httpguts.ValidHeaderFieldValue(v) { return nil, badRequestError("invalid header value") } } } delete(req.Header, "Host") ctx, cancelCtx := context.WithCancel(ctx) req.ctx = ctx req.RemoteAddr = c.remoteAddr req.TLS = c.tlsState if body, ok := req.Body.(*body); ok { body.doEarlyClose = true } // Adjust the read deadline if necessary. if !hdrDeadline.Equal(wholeReqDeadline) { c.rwc.SetReadDeadline(wholeReqDeadline) } w = &response{ conn: c, cancelCtx: cancelCtx, req: req, reqBody: req.Body, handlerHeader: make(Header), contentLength: -1, closeNotifyCh: make(chan bool, 1), // We populate these ahead of time so we're not // reading from req.Header after their Handler starts // and maybe mutates it (Issue 14940) wants10KeepAlive: req.wantsHttp10KeepAlive(), wantsClose: req.wantsClose(), } if isH2Upgrade { w.closeAfterReply = true } w.cw.res = w w.w = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize) return w, nil } // http1ServerSupportsRequest reports whether Go's HTTP/1.x server // supports the given request. func http1ServerSupportsRequest(req *Request) bool { if req.ProtoMajor == 1 { return true } // Accept "PRI * HTTP/2.0" upgrade requests, so Handlers can // wire up their own HTTP/2 upgrades. if req.ProtoMajor == 2 && req.ProtoMinor == 0 && req.Method == "PRI" && req.RequestURI == "*" { return true } // Reject HTTP/0.x, and all other HTTP/2+ requests (which // aren't encoded in ASCII anyway). return false } func (w *response) Header() Header { if w.cw.header == nil && w.wroteHeader && !w.cw.wroteHeader { // Accessing the header between logically writing it // and physically writing it means we need to allocate // a clone to snapshot the logically written state. w.cw.header = w.handlerHeader.Clone() } w.calledHeader = true return w.handlerHeader } // maxPostHandlerReadBytes is the max number of Request.Body bytes not // consumed by a handler that the server will read from the client // in order to keep a connection alive. If there are more bytes // than this, the server, to be paranoid, instead sends a // "Connection close" response. // // This number is approximately what a typical machine's TCP buffer // size is anyway. (if we have the bytes on the machine, we might as // well read them) const maxPostHandlerReadBytes = 256 << 10 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). // But for now any three digits. // // We used to send "HTTP/1.1 000 0" on the wire in responses but there's // no equivalent bogus thing we can realistically send in HTTP/2, // so we'll consistently panic instead and help people find their bugs // early. (We can't return an error from WriteHeader even if we wanted to.) if code < 100 || code > 999 { panic(fmt.Sprintf("invalid WriteHeader code %v", code)) } } // relevantCaller searches the call stack for the first function outside of net/http. // The purpose of this function is to provide more helpful error messages. func relevantCaller() runtime.Frame { pc := make([]uintptr, 16) n := runtime.Callers(1, pc) frames := runtime.CallersFrames(pc[:n]) var frame runtime.Frame for { frame, more := frames.Next() if !strings.HasPrefix(frame.Function, "net/http.") { return frame } if !more { break } } return frame } func (w *response) WriteHeader(code int) { if w.conn.hijacked() { caller := relevantCaller() w.conn.server.logf("http: response.WriteHeader on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line) return } if w.wroteHeader { caller := relevantCaller() w.conn.server.logf("http: superfluous response.WriteHeader call from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line) return } checkWriteHeaderCode(code) if code < 101 || code > 199 { // Sending a 100 Continue or any non-1xx header disables the // automatically-sent 100 Continue from Request.Body.Read. w.disableWriteContinue() } // Handle informational headers. // // We shouldn't send any further headers after 101 Switching Protocols, // so it takes the non-informational path. if code >= 100 && code <= 199 && code != StatusSwitchingProtocols { 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 if w.calledHeader && w.cw.header == nil { w.cw.header = w.handlerHeader.Clone() } if cl := w.handlerHeader.get("Content-Length"); cl != "" { v, err := strconv.ParseInt(cl, 10, 64) if err == nil && v >= 0 { w.contentLength = v } else { w.conn.server.logf("http: invalid Content-Length of %q", cl) w.handlerHeader.Del("Content-Length") } } } // extraHeader is the set of headers sometimes added by chunkWriter.writeHeader. // This type is used to avoid extra allocations from cloning and/or populating // the response Header map and all its 1-element slices. type extraHeader struct { contentType string connection string transferEncoding string date []byte // written if not nil contentLength []byte // written if not nil } // Sorted the same as extraHeader.Write's loop. var extraHeaderKeys = [][]byte{ []byte("Content-Type"), []byte("Connection"), []byte("Transfer-Encoding"), } var ( headerContentLength = []byte("Content-Length: ") headerDate = []byte("Date: ") ) // Write writes the headers described in h to w. // // This method has a value receiver, despite the somewhat large size // of h, because it prevents an allocation. The escape analysis isn't // smart enough to realize this function doesn't mutate h. func (h extraHeader) Write(w *bufio.Writer) { if h.date != nil { w.Write(headerDate) w.Write(h.date) w.Write(crlf) } if h.contentLength != nil { w.Write(headerContentLength) w.Write(h.contentLength) w.Write(crlf) } for i, v := range []string{h.contentType, h.connection, h.transferEncoding} { if v != "" { w.Write(extraHeaderKeys[i]) w.Write(colonSpace) w.WriteString(v) w.Write(crlf) } } } // writeHeader finalizes the header sent to the client and writes it // 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 // set explicitly. It's also used to set the Content-Length, if the // total body size was small and the handler has already finished // running. func (cw *chunkWriter) writeHeader(p []byte) { if cw.wroteHeader { return } cw.wroteHeader = true w := cw.res keepAlivesEnabled := w.conn.server.doKeepAlives() isHEAD := w.req.Method == "HEAD" // header is written out to w.conn.buf below. Depending on the // state of the handler, we either own the map or not. If we // don't own it, the exclude map is created lazily for // WriteSubset to remove headers. The setHeader struct holds // headers we need to add. header := cw.header owned := header != nil if !owned { header = w.handlerHeader } var excludeHeader map[string]bool delHeader := func(key string) { if owned { header.Del(key) return } if _, ok := header[key]; !ok { return } if excludeHeader == nil { excludeHeader = make(map[string]bool) } excludeHeader[key] = true } var setHeader extraHeader // Don't write out the fake "Trailer:foo" keys. See TrailerPrefix. trailers := false for k := range cw.header { if strings.HasPrefix(k, TrailerPrefix) { if excludeHeader == nil { excludeHeader = make(map[string]bool) } excludeHeader[k] = true trailers = true } } for _, v := range cw.header["Trailer"] { trailers = true foreachHeaderElement(v, cw.res.declareTrailer) } te := header.get("Transfer-Encoding") hasTE := te != "" // If the handler is done but never sent a Content-Length // response header and this is our first (and last) write, set // it, even to zero. This helps HTTP/1.0 clients keep their // "keep-alive" connections alive. // Exceptions: 304/204/1xx responses never get Content-Length, and if // it was a HEAD request, we don't know the difference between // 0 actual bytes and 0 bytes because the handler noticed it // was a HEAD request and chose not to write anything. So for // HEAD, the handler should either write the Content-Length or // write non-zero bytes. If it's actually 0 bytes and the // handler never looked at the Request.Method, we just don't // 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.Load() && !trailers && !hasTE && bodyAllowedForStatus(w.status) && !header.has("Content-Length") && (!isHEAD || len(p) > 0) { w.contentLength = int64(len(p)) setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10) } // If this was an HTTP/1.0 request with keep-alive and we sent a // Content-Length back, we can make this a keep-alive response ... if w.wants10KeepAlive && keepAlivesEnabled { sentLength := header.get("Content-Length") != "" if sentLength && header.get("Connection") == "keep-alive" { w.closeAfterReply = false } } // Check for an explicit (and valid) Content-Length header. hasCL := w.contentLength != -1 if w.wants10KeepAlive && (isHEAD || hasCL || !bodyAllowedForStatus(w.status)) { _, connectionHeaderSet := header["Connection"] if !connectionHeaderSet { setHeader.connection = "keep-alive" } } else if !w.req.ProtoAtLeast(1, 1) || w.wantsClose { w.closeAfterReply = true } if header.get("Connection") == "close" || !keepAlivesEnabled { w.closeAfterReply = true } // If the client wanted a 100-continue but we never sent it to // them (or, more strictly: we never finished reading their // request body), don't reuse this connection. // // This behavior was first added on the theory that we don't know // if the next bytes on the wire are going to be the remainder of // the request body or the subsequent request (see issue 11549), // but that's not correct: If we keep using the connection, // the client is required to send the request body whether we // asked for it or not. // // We probably do want to skip reusing the connection in most cases, // however. If the client is offering a large request body that we // don't intend to use, then it's better to close the connection // than to read the body. For now, assume that if we're sending // headers, the handler is done reading the body and we should // drop the connection if we haven't seen EOF. if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF.Load() { w.closeAfterReply = true } // We do this by default because there are a number of clients that // send a full request before starting to read the response, and they // can deadlock if we start writing the response with unconsumed body // remaining. See Issue 15527 for some history. // // If full duplex mode has been enabled with ResponseController.EnableFullDuplex, // then leave the request body alone. // // We don't take this path when w.closeAfterReply is set. // We may not need to consume the request to get ready for the next one // (since we're closing the conn), but a client which sends a full request // before reading a response may deadlock in this case. // This behavior has been present since CL 5268043 (2011), however, // so it doesn't seem to be causing problems. if w.req.ContentLength != 0 && !w.closeAfterReply && !w.fullDuplex { var discard, tooBig bool switch bdy := w.req.Body.(type) { case *expectContinueReader: // We only get here if we have already fully consumed the request body // (see above). case *body: bdy.mu.Lock() switch { case bdy.closed: if !bdy.sawEOF { // Body was closed in handler with non-EOF error. w.closeAfterReply = true } case bdy.unreadDataSizeLocked() >= maxPostHandlerReadBytes: tooBig = true default: discard = true } bdy.mu.Unlock() default: discard = true } if discard { _, err := io.CopyN(io.Discard, w.reqBody, maxPostHandlerReadBytes+1) switch err { case nil: // There must be even more data left over. tooBig = true case ErrBodyReadAfterClose: // Body was already consumed and closed. case io.EOF: // The remaining body was just consumed, close it. err = w.reqBody.Close() if err != nil { w.closeAfterReply = true } default: // Some other kind of error occurred, like a read timeout, or // corrupt chunked encoding. In any case, whatever remains // on the wire must not be parsed as another HTTP request. w.closeAfterReply = true } } if tooBig { w.requestTooLarge() delHeader("Connection") setHeader.connection = "close" } } code := w.status if bodyAllowedForStatus(code) { // If no content type, apply sniffing algorithm to body. _, haveType := header["Content-Type"] // If the Content-Encoding was set and is non-blank, // we shouldn't sniff the body. See Issue 31753. ce := header.Get("Content-Encoding") hasCE := len(ce) > 0 if !hasCE && !haveType && !hasTE && len(p) > 0 { setHeader.contentType = DetectContentType(p) } } else { for _, k := range suppressedHeaders(code) { delHeader(k) } } if !header.has("Date") { setHeader.date = appendTime(cw.res.dateBuf[:0], time.Now()) } if hasCL && hasTE && te != "identity" { // TODO: return an error if WriteHeader gets a return parameter // For now just ignore the Content-Length. w.conn.server.logf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d", te, w.contentLength) delHeader("Content-Length") hasCL = false } if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) || code == StatusNoContent { // Response has no body. delHeader("Transfer-Encoding") } else if hasCL { // Content-Length has been provided, so no chunking is to be done. delHeader("Transfer-Encoding") } else if w.req.ProtoAtLeast(1, 1) { // HTTP/1.1 or greater: Transfer-Encoding has been set to identity, and no // content-length has been provided. The connection must be closed after the // reply is written, and no chunking is to be done. This is the setup // recommended in the Server-Sent Events candidate recommendation 11, // section 8. if hasTE && te == "identity" { cw.chunking = false w.closeAfterReply = true delHeader("Transfer-Encoding") } else { // HTTP/1.1 or greater: use chunked transfer encoding // to avoid closing the connection at EOF. cw.chunking = true setHeader.transferEncoding = "chunked" if hasTE && te == "chunked" { // We will send the chunked Transfer-Encoding header later. delHeader("Transfer-Encoding") } } } else { // HTTP version < 1.1: cannot do chunked transfer // encoding and we don't know the Content-Length so // signal EOF by closing connection. w.closeAfterReply = true delHeader("Transfer-Encoding") // in case already set } // Cannot use Content-Length with non-identity Transfer-Encoding. if cw.chunking { delHeader("Content-Length") } if !w.req.ProtoAtLeast(1, 0) { return } // Only override the Connection header if it is not a successful // protocol switch response and if KeepAlives are not enabled. // See https://golang.org/issue/36381. delConnectionHeader := w.closeAfterReply && (!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) && !isProtocolSwitchResponse(w.status, header) if delConnectionHeader { delHeader("Connection") if w.req.ProtoAtLeast(1, 1) { setHeader.connection = "close" } } writeStatusLine(w.conn.bufw, w.req.ProtoAtLeast(1, 1), code, w.statusBuf[:]) 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 // in RFC 7230 section 7 and calls fn for each non-empty element. func foreachHeaderElement(v string, fn func(string)) { v = textproto.TrimString(v) if v == "" { return } if !strings.Contains(v, ",") { fn(v) return } for _, f := range strings.Split(v, ",") { if f = textproto.TrimString(f); f != "" { fn(f) } } } // writeStatusLine writes an HTTP/1.x Status-Line (RFC 7230 Section 3.1.2) // to bw. is11 is whether the HTTP request is HTTP/1.1. false means HTTP/1.0. // code is the response status code. // scratch is an optional scratch buffer. If it has at least capacity 3, it's used. func writeStatusLine(bw *bufio.Writer, is11 bool, code int, scratch []byte) { if is11 { bw.WriteString("HTTP/1.1 ") } else { bw.WriteString("HTTP/1.0 ") } if text := StatusText(code); text != "" { bw.Write(strconv.AppendInt(scratch[:0], int64(code), 10)) bw.WriteByte(' ') bw.WriteString(text) bw.WriteString("\r\n") } else { // don't worry about performance fmt.Fprintf(bw, "%03d status code %d\r\n", code, code) } } // bodyAllowed reports whether a Write is allowed for this response type. // It's illegal to call this before the header has been flushed. func (w *response) bodyAllowed() bool { if !w.wroteHeader { panic("") } return bodyAllowedForStatus(w.status) } // The Life Of A Write is like this: // // Handler starts. No header has been sent. The handler can either // write a header, or just start writing. Writing before sending a header // sends an implicitly empty 200 OK header. // // If the handler didn't declare a Content-Length up front, we either // go into chunking mode or, if the handler finishes running before // the chunking buffer size, we compute a Content-Length and send that // in the header instead. // // Likewise, if the handler didn't set a Content-Type, we sniff that // from the initial chunk of output. // // The Writers are wired together like: // // 1. *response (the ResponseWriter) -> // 2. (*response).w, a [*bufio.Writer] of bufferBeforeChunkingSize bytes -> // 3. chunkWriter.Writer (whose writeHeader finalizes Content-Length/Type) // and which writes the chunk headers, if needed -> // 4. conn.bufw, a *bufio.Writer of default (4kB) bytes, writing to -> // 5. checkConnErrorWriter{c}, which notes any non-nil error on Write // and populates c.werr with it if so, but otherwise writes to -> // 6. the rwc, the [net.Conn]. // // TODO(bradfitz): short-circuit some of the buffering when the // initial header contains both a Content-Type and Content-Length. // Also short-circuit in (1) when the header's been sent and not in // chunking mode, writing directly to (4) instead, if (2) has no // buffered data. More generally, we could short-circuit from (1) to // (3) even in chunking mode if the write size from (1) is over some // threshold and nothing is in (2). The answer might be mostly making // bufferBeforeChunkingSize smaller and having bufio's fast-paths deal // with this instead. func (w *response) Write(data []byte) (n int, err error) { return w.write(len(data), data, "") } func (w *response) WriteString(data string) (n int, err error) { return w.write(len(data), nil, data) } // either dataB or dataS is non-zero. func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) { if w.conn.hijacked() { if lenData > 0 { caller := relevantCaller() w.conn.server.logf("http: response.Write on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line) } return 0, ErrHijacked } if w.canWriteContinue.Load() { // Body reader wants to write 100 Continue but hasn't yet. Tell it not to. w.disableWriteContinue() } if !w.wroteHeader { w.WriteHeader(StatusOK) } if lenData == 0 { return 0, nil } if !w.bodyAllowed() { return 0, ErrBodyNotAllowed } w.written += int64(lenData) // ignoring errors, for errorKludge if w.contentLength != -1 && w.written > w.contentLength { return 0, ErrContentLength } if dataB != nil { return w.w.Write(dataB) } else { return w.w.WriteString(dataS) } } func (w *response) finishRequest() { w.handlerDone.Store(true) if !w.wroteHeader { w.WriteHeader(StatusOK) } w.w.Flush() putBufioWriter(w.w) w.cw.close() w.conn.bufw.Flush() w.conn.r.abortPendingRead() // Close the body (regardless of w.closeAfterReply) so we can // re-use its bufio.Reader later safely. w.reqBody.Close() if w.req.MultipartForm != nil { w.req.MultipartForm.RemoveAll() } } // shouldReuseConnection reports whether the underlying TCP connection can be reused. // It must only be called after the handler is done executing. func (w *response) shouldReuseConnection() bool { if w.closeAfterReply { // The request or something set while executing the // handler indicated we shouldn't reuse this // connection. return false } if w.req.Method != "HEAD" && w.contentLength != -1 && w.bodyAllowed() && w.contentLength != w.written { // Did not write enough. Avoid getting out of sync. return false } // There was some error writing to the underlying connection // during the request, so don't re-use this conn. if w.conn.werr != nil { return false } if w.closedRequestBodyEarly() { return false } return true } func (w *response) closedRequestBodyEarly() bool { body, ok := w.req.Body.(*body) return ok && body.didEarlyClose() } func (w *response) Flush() { w.FlushError() } func (w *response) FlushError() error { if !w.wroteHeader { w.WriteHeader(StatusOK) } err := w.w.Flush() e2 := w.cw.flush() if err == nil { err = e2 } return err } func (c *conn) finalFlush() { if c.bufr != nil { // Steal the bufio.Reader (~4KB worth of memory) and its associated // reader for a future connection. 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.bufw) c.bufw = nil } } // Close the connection. func (c *conn) close() { c.finalFlush() c.rwc.Close() } // rstAvoidanceDelay is the amount of time we sleep after closing the // write side of a TCP connection before closing the entire socket. // By sleeping, we increase the chances that the client sees our FIN // and processes its final data before they process the subsequent RST // from closing a connection with known unread data. // This RST seems to occur mostly on BSD systems. (And Windows?) // This timeout is somewhat arbitrary (~latency around the planet), // and may be modified by tests. // // TODO(bcmills): This should arguably be a server configuration parameter, // not a hard-coded value. var rstAvoidanceDelay = 500 * time.Millisecond type closeWriter interface { CloseWrite() error } var _ closeWriter = (*net.TCPConn)(nil) // closeWriteAndWait flushes any outstanding data and sends a FIN packet (if // client is connected via TCP), signaling that we're done. We then // pause for a bit, hoping the client processes it before any // subsequent RST. // // See https://golang.org/issue/3595 func (c *conn) closeWriteAndWait() { c.finalFlush() if tcp, ok := c.rwc.(closeWriter); ok { tcp.CloseWrite() } // When we return from closeWriteAndWait, the caller will fully close the // connection. If client is still writing to the connection, this will cause // the write to fail with ECONNRESET or similar. Unfortunately, many TCP // implementations will also drop unread packets from the client's read buffer // when a write fails, causing our final response to be truncated away too. // // As a result, https://www.rfc-editor.org/rfc/rfc7230#section-6.6 recommends // that “[t]he server … continues to read from the connection until it // receives a corresponding close by the client, or until the server is // reasonably certain that its own TCP stack has received the client's // acknowledgement of the packet(s) containing the server's last response.” // // Unfortunately, we have no straightforward way to be “reasonably certain” // that we have received the client's ACK, and at any rate we don't want to // allow a misbehaving client to soak up server connections indefinitely by // withholding an ACK, nor do we want to go through the complexity or overhead // of using low-level APIs to figure out when a TCP round-trip has completed. // // Instead, we declare that we are “reasonably certain” that we received the // ACK if maxRSTAvoidanceDelay has elapsed. time.Sleep(rstAvoidanceDelay) } // validNextProto reports whether the proto is a valid ALPN protocol name. // Everything is valid except the empty string and built-in protocol types, // so that those can't be overridden with alternate implementations. func validNextProto(proto string) bool { switch proto { case "", "http/1.1", "http/1.0": return false } return true } const ( runHooks = true skipHooks = false ) func (c *conn) setState(nc net.Conn, state ConnState, runHook bool) { srv := c.server switch state { case StateNew: srv.trackConn(c, true) case StateHijacked, StateClosed: srv.trackConn(c, false) } if state > 0xff || state < 0 { panic("internal error") } packedState := uint64(time.Now().Unix()<<8) | uint64(state) c.curState.Store(packedState) if !runHook { return } if hook := srv.ConnState; hook != nil { hook(nc, state) } } func (c *conn) getState() (state ConnState, unixSec int64) { packedState := c.curState.Load() return ConnState(packedState & 0xff), int64(packedState >> 8) } // 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 embedded errors. func badRequestError(e string) error { return statusError{StatusBadRequest, e} } // statusError is an error used to respond to a request with an HTTP status. // The text should be plain text without user info or other embedded errors. type statusError struct { code int text string } func (e statusError) Error() string { return StatusText(e.code) + ": " + e.text } // ErrAbortHandler is a sentinel panic value to abort a handler. // While any panic from ServeHTTP aborts the response to the client, // panicking with ErrAbortHandler also suppresses logging of a stack // trace to the server's error log. var ErrAbortHandler = errors.New("net/http: abort Handler") // isCommonNetReadError reports whether err is a common error // encountered during reading a request off the network when the // client has gone away or had its read fail somehow. This is used to // determine which logs are interesting enough to log about. func isCommonNetReadError(err error) bool { if err == io.EOF { return true } if neterr, ok := err.(net.Error); ok && neterr.Timeout() { return true } if oe, ok := err.(*net.OpError); ok && oe.Op == "read" { return true } return false } // Serve a new connection. func (c *conn) serve(ctx context.Context) { if ra := c.rwc.RemoteAddr(); ra != nil { c.remoteAddr = ra.String() } ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr()) var inFlightResponse *response defer func() { if err := recover(); err != nil && err != ErrAbortHandler { const size = 64 << 10 buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf) } if inFlightResponse != nil { inFlightResponse.cancelCtx() inFlightResponse.disableWriteContinue() } if !c.hijacked() { if inFlightResponse != nil { inFlightResponse.conn.r.abortPendingRead() inFlightResponse.reqBody.Close() } c.close() c.setState(c.rwc, StateClosed, runHooks) } }() if tlsConn, ok := c.rwc.(*tls.Conn); ok { tlsTO := c.server.tlsHandshakeTimeout() if tlsTO > 0 { dl := time.Now().Add(tlsTO) c.rwc.SetReadDeadline(dl) c.rwc.SetWriteDeadline(dl) } if err := tlsConn.HandshakeContext(ctx); err != nil { // If the handshake failed due to the client not speaking // TLS, assume they're speaking plaintext HTTP and write a // 400 response on the TLS conn's underlying net.Conn. var reason string if re, ok := err.(tls.RecordHeaderError); ok && re.Conn != nil && tlsRecordHeaderLooksLikeHTTP(re.RecordHeader) { io.WriteString(re.Conn, "HTTP/1.0 400 Bad Request\r\n\r\nClient sent an HTTP request to an HTTPS server.\n") re.Conn.Close() reason = "client sent an HTTP request to an HTTPS server" } else { reason = err.Error() } c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), reason) return } // Restore Conn-level deadlines. if tlsTO > 0 { c.rwc.SetReadDeadline(time.Time{}) c.rwc.SetWriteDeadline(time.Time{}) } c.tlsState = new(tls.ConnectionState) *c.tlsState = tlsConn.ConnectionState() if proto := c.tlsState.NegotiatedProtocol; validNextProto(proto) { if fn := c.server.TLSNextProto[proto]; fn != nil { h := initALPNRequest{ctx, tlsConn, serverHandler{c.server}} // Mark freshly created HTTP/2 as active and prevent any server state hooks // from being run on these connections. This prevents closeIdleConns from // closing such connections. See issue https://golang.org/issue/39776. c.setState(c.rwc, StateActive, skipHooks) fn(c.server, tlsConn, h) } return } } // HTTP/1.x from here on. ctx, cancelCtx := context.WithCancel(ctx) c.cancelCtx = cancelCtx defer cancelCtx() c.r = &connReader{conn: c} c.bufr = newBufioReader(c.r) c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10) for { w, err := c.readRequest(ctx) if c.r.remain != c.server.initialReadLimitSize() { // If we read any bytes off the wire, we're active. c.setState(c.rwc, StateActive, runHooks) } if err != nil { const errorHeaders = "\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\n" switch { case err == errTooLarge: // Their HTTP client may or may not be // able to read this if we're // responding to them and hanging up // while they're still writing their // request. Undefined behavior. const publicErr = "431 Request Header Fields Too Large" fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr) c.closeWriteAndWait() return case isUnsupportedTEError(err): // Respond as per RFC 7230 Section 3.3.1 which says, // A server that receives a request message with a // transfer coding it does not understand SHOULD // respond with 501 (Unimplemented). code := StatusNotImplemented // We purposefully aren't echoing back the transfer-encoding's value, // so as to mitigate the risk of cross side scripting by an attacker. fmt.Fprintf(c.rwc, "HTTP/1.1 %d %s%sUnsupported transfer encoding", code, StatusText(code), errorHeaders) return case isCommonNetReadError(err): return // don't reply default: if v, ok := err.(statusError); ok { fmt.Fprintf(c.rwc, "HTTP/1.1 %d %s: %s%s%d %s: %s", v.code, StatusText(v.code), v.text, errorHeaders, v.code, StatusText(v.code), v.text) return } const publicErr = "400 Bad Request" fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr) return } } // Expect 100 Continue support req := w.req if req.expectsContinue() { if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 { // Wrap the Body reader with one that replies on the connection req.Body = &expectContinueReader{readCloser: req.Body, resp: w} w.canWriteContinue.Store(true) } } else if req.Header.get("Expect") != "" { w.sendExpectationFailed() return } c.curReq.Store(w) if requestBodyRemains(req.Body) { registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead) } else { w.conn.r.startBackgroundRead() } // HTTP cannot have multiple simultaneous active requests.[*] // Until the server replies to this request, it can't read another, // so we might as well run the handler in this goroutine. // [*] Not strictly true: HTTP pipelining. We could let them all process // in parallel even if their responses need to be serialized. // But we're not going to implement HTTP pipelining because it // was never deployed in the wild and the answer is HTTP/2. inFlightResponse = w serverHandler{c.server}.ServeHTTP(w, w.req) inFlightResponse = nil w.cancelCtx() if c.hijacked() { return } w.finishRequest() c.rwc.SetWriteDeadline(time.Time{}) if !w.shouldReuseConnection() { if w.requestBodyLimitHit || w.closedRequestBodyEarly() { c.closeWriteAndWait() } return } c.setState(c.rwc, StateIdle, runHooks) c.curReq.Store(nil) if !w.conn.server.doKeepAlives() { // We're in shutdown mode. We might've replied // to the user without "Connection: close" and // they might think they can send another // request, but such is life with HTTP/1.1. return } if d := c.server.idleTimeout(); d > 0 { c.rwc.SetReadDeadline(time.Now().Add(d)) } else { c.rwc.SetReadDeadline(time.Time{}) } // Wait for the connection to become readable again before trying to // read the next request. This prevents a ReadHeaderTimeout or // ReadTimeout from starting until the first bytes of the next request // have been received. if _, err := c.bufr.Peek(4); err != nil { return } c.rwc.SetReadDeadline(time.Time{}) } } func (w *response) sendExpectationFailed() { // TODO(bradfitz): let ServeHTTP handlers handle // requests with non-standard expectation[s]? Seems // theoretical at best, and doesn't fit into the // current ServeHTTP model anyway. We'd need to // make the ResponseWriter an optional // "ExpectReplier" interface or something. // // For now we'll just obey RFC 7231 5.1.1 which says // "A server that receives an Expect field-value other // than 100-continue MAY respond with a 417 (Expectation // Failed) status code to indicate that the unexpected // expectation cannot be met." w.Header().Set("Connection", "close") w.WriteHeader(StatusExpectationFailed) w.finishRequest() } // 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.Load() { panic("net/http: Hijack called after ServeHTTP finished") } w.disableWriteContinue() if w.wroteHeader { w.cw.flush() } c := w.conn c.mu.Lock() defer c.mu.Unlock() // Release the bufioWriter that writes to the chunk writer, it is not // used after a connection has been hijacked. rwc, buf, err = c.hijackLocked() if err == nil { putBufioWriter(w.w) w.w = nil } return rwc, buf, err } func (w *response) CloseNotify() <-chan bool { if w.handlerDone.Load() { panic("net/http: CloseNotify called after ServeHTTP finished") } return w.closeNotifyCh } 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 == NoBody { 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] that calls f. type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) } // Helper handlers // Error replies to the request with the specified error message and HTTP code. // It does not otherwise end the request; the caller should ensure no further // writes are done to w. // The error message should be plain text. // // Error deletes the Content-Length header, // sets Content-Type to “text/plain; charset=utf-8”, // and sets X-Content-Type-Options to “nosniff”. // This configures the header properly for the error message, // in case the caller had set it up expecting a successful output. func Error(w ResponseWriter, error string, code int) { h := w.Header() // Delete the Content-Length header, which might be for some other content. // Assuming the error string fits in the writer's buffer, we'll figure // out the correct Content-Length for it later. // // We don't delete Content-Encoding, because some middleware sets // Content-Encoding: gzip and wraps the ResponseWriter to compress on-the-fly. // See https://go.dev/issue/66343. h.Del("Content-Length") // There might be content type already set, but we reset it to // text/plain for the error message. h.Set("Content-Type", "text/plain; charset=utf-8") h.Set("X-Content-Type-Options", "nosniff") w.WriteHeader(code) fmt.Fprintln(w, error) } // NotFound replies to the request with an HTTP 404 not found error. func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) } // NotFoundHandler returns a simple request handler // that replies to each request with a “404 page not found” reply. func NotFoundHandler() Handler { return HandlerFunc(NotFound) } // StripPrefix returns a handler that serves HTTP requests by removing the // given prefix from the request URL's Path (and RawPath if set) and invoking // the handler h. StripPrefix handles a request for a path that doesn't begin // with prefix by replying with an HTTP 404 not found error. The prefix must // match exactly: if the prefix in the request contains escaped characters // the reply is also an HTTP 404 not found error. func StripPrefix(prefix string, h Handler) Handler { if prefix == "" { return h } return HandlerFunc(func(w ResponseWriter, r *Request) { p := strings.TrimPrefix(r.URL.Path, prefix) rp := strings.TrimPrefix(r.URL.RawPath, prefix) if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) { r2 := new(Request) *r2 = *r r2.URL = new(url.URL) *r2.URL = *r.URL r2.URL.Path = p r2.URL.RawPath = rp h.ServeHTTP(w, r2) } else { NotFound(w, r) } }) } // 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]. // // If the Content-Type header has not been set, [Redirect] sets it // to "text/html; charset=utf-8" and writes a small HTML body. // Setting the Content-Type header to any value, including nil, // disables that behavior. func Redirect(w ResponseWriter, r *Request, url string, code int) { if u, err := urlpkg.Parse(url); err == nil { // If url was relative, make its path absolute by // combining with request path. // The client would probably do this for us, // but doing it ourselves is more reliable. // See RFC 7231, section 7.1.2 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 url == "" || url[0] != '/' { // make relative path absolute olddir, _ := path.Split(oldpath) url = olddir + url } var query string if i := strings.Index(url, "?"); i != -1 { url, query = url[:i], url[i:] } // clean up but preserve trailing slash trailing := strings.HasSuffix(url, "/") url = path.Clean(url) if trailing && !strings.HasSuffix(url, "/") { url += "/" } url += query } } h := w.Header() // RFC 7231 notes that a short HTML body is usually included in // the response because older user agents may not understand 301/307. // Do it only if the request didn't already have a Content-Type header. _, hadCT := h["Content-Type"] h.Set("Location", hexEscapeNonASCII(url)) if !hadCT && (r.Method == "GET" || r.Method == "HEAD") { h.Set("Content-Type", "text/html; charset=utf-8") } w.WriteHeader(code) // Shouldn't send the body for POST or HEAD; that leaves GET. if !hadCT && r.Method == "GET" { body := "" + StatusText(code) + ".\n" fmt.Fprintln(w, body) } } var htmlReplacer = strings.NewReplacer( "&", "&", "<", "<", ">", ">", // """ is shorter than """. `"`, """, // "'" is shorter than "'" and apos was not in HTML until HTML5. "'", "'", ) func htmlEscape(s string) string { return htmlReplacer.Replace(s) } // Redirect to a fixed URL type redirectHandler struct { url string code int } func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) { Redirect(w, r, rh.url, rh.code) } // 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} } // ServeMux is an HTTP request multiplexer. // It matches the URL of each incoming request against a list of registered // patterns and calls the handler for the pattern that // most closely matches the URL. // // # Patterns // // Patterns can match the method, host and path of a request. // Some examples: // // - "/index.html" matches the path "/index.html" for any host and method. // - "GET /static/" matches a GET request whose path begins with "/static/". // - "example.com/" matches any request to the host "example.com". // - "example.com/{$}" matches requests with host "example.com" and path "/". // - "/b/{bucket}/o/{objectname...}" matches paths whose first segment is "b" // and whose third segment is "o". The name "bucket" denotes the second // segment and "objectname" denotes the remainder of the path. // // In general, a pattern looks like // // [METHOD ][HOST]/[PATH] // // All three parts are optional; "/" is a valid pattern. // If METHOD is present, it must be followed by at least one space or tab. // // Literal (that is, non-wildcard) parts of a pattern match // the corresponding parts of a request case-sensitively. // // A pattern with no method matches every method. A pattern // with the method GET matches both GET and HEAD requests. // Otherwise, the method must match exactly. // // A pattern with no host matches every host. // A pattern with a host matches URLs on that host only. // // A path can include wildcard segments of the form {NAME} or {NAME...}. // For example, "/b/{bucket}/o/{objectname...}". // The wildcard name must be a valid Go identifier. // Wildcards must be full path segments: they must be preceded by a slash and followed by // either a slash or the end of the string. // For example, "/b_{bucket}" is not a valid pattern. // // Normally a wildcard matches only a single path segment, // ending at the next literal slash (not %2F) in the request URL. // But if the "..." is present, then the wildcard matches the remainder of the URL path, including slashes. // (Therefore it is invalid for a "..." wildcard to appear anywhere but at the end of a pattern.) // The match for a wildcard can be obtained by calling [Request.PathValue] with the wildcard's name. // A trailing slash in a path acts as an anonymous "..." wildcard. // // The special wildcard {$} matches only the end of the URL. // For example, the pattern "/{$}" matches only the path "/", // whereas the pattern "/" matches every path. // // For matching, both pattern paths and incoming request paths are unescaped segment by segment. // So, for example, the path "/a%2Fb/100%25" is treated as having two segments, "a/b" and "100%". // The pattern "/a%2fb/" matches it, but the pattern "/a/b/" does not. // // # Precedence // // If two or more patterns match a request, then the most specific pattern takes precedence. // A pattern P1 is more specific than P2 if P1 matches a strict subset of P2’s requests; // that is, if P2 matches all the requests of P1 and more. // If neither is more specific, then the patterns conflict. // There is one exception to this rule, for backwards compatibility: // if two patterns would otherwise conflict and one has a host while the other does not, // then the pattern with the host takes precedence. // If a pattern passed to [ServeMux.Handle] or [ServeMux.HandleFunc] conflicts with // another pattern that is already registered, those functions panic. // // As an example of the general rule, "/images/thumbnails/" is more specific than "/images/", // so both can be registered. // The former matches paths beginning with "/images/thumbnails/" // and the latter will match any other path in the "/images/" subtree. // // As another example, consider the patterns "GET /" and "/index.html": // both match a GET request for "/index.html", but the former pattern // matches all other GET and HEAD requests, while the latter matches any // request for "/index.html" that uses a different method. // The patterns conflict. // // # Trailing-slash redirection // // Consider a [ServeMux] with a handler for a subtree, registered using a trailing slash or "..." wildcard. // If the ServeMux receives a request for the subtree root without a trailing slash, // it redirects the request by adding the trailing slash. // This behavior can be overridden with a separate registration for the path without // the trailing slash or "..." wildcard. For example, registering "/images/" causes ServeMux // to redirect a request for "/images" to "/images/", unless "/images" has // been registered separately. // // # Request sanitizing // // ServeMux also takes care of sanitizing the URL request path and the Host // header, stripping the port number and redirecting any request containing . or // .. segments or repeated slashes to an equivalent, cleaner URL. // // # Compatibility // // The pattern syntax and matching behavior of ServeMux changed significantly // in Go 1.22. To restore the old behavior, set the GODEBUG environment variable // to "httpmuxgo121=1". This setting is read once, at program startup; changes // during execution will be ignored. // // The backwards-incompatible changes include: // - Wildcards are just ordinary literal path segments in 1.21. // For example, the pattern "/{x}" will match only that path in 1.21, // but will match any one-segment path in 1.22. // - In 1.21, no pattern was rejected, unless it was empty or conflicted with an existing pattern. // In 1.22, syntactically invalid patterns will cause [ServeMux.Handle] and [ServeMux.HandleFunc] to panic. // For example, in 1.21, the patterns "/{" and "/a{x}" match themselves, // but in 1.22 they are invalid and will cause a panic when registered. // - In 1.22, each segment of a pattern is unescaped; this was not done in 1.21. // For example, in 1.22 the pattern "/%61" matches the path "/a" ("%61" being the URL escape sequence for "a"), // but in 1.21 it would match only the path "/%2561" (where "%25" is the escape for the percent sign). // - When matching patterns to paths, in 1.22 each segment of the path is unescaped; in 1.21, the entire path is unescaped. // This change mostly affects how paths with %2F escapes adjacent to slashes are treated. // See https://go.dev/issue/21955 for details. type ServeMux struct { mu sync.RWMutex tree routingNode index routingIndex patterns []*pattern // TODO(jba): remove if possible mux121 serveMux121 // used only when GODEBUG=httpmuxgo121=1 } // NewServeMux allocates and returns a new [ServeMux]. func NewServeMux() *ServeMux { return &ServeMux{} } // DefaultServeMux is the default [ServeMux] used by [Serve]. var DefaultServeMux = &defaultServeMux var defaultServeMux ServeMux // cleanPath returns the canonical path for p, eliminating . and .. elements. func cleanPath(p string) string { if p == "" { return "/" } if p[0] != '/' { p = "/" + p } np := path.Clean(p) // path.Clean removes trailing slash except for root; // put the trailing slash back if necessary. if p[len(p)-1] == '/' && np != "/" { // Fast path for common case of p being the string we want: if len(p) == len(np)+1 && strings.HasPrefix(p, np) { np = p } else { np += "/" } } return np } // stripHostPort returns h without any trailing ":". func stripHostPort(h string) string { // If no port on host, return unchanged if !strings.Contains(h, ":") { return h } host, _, err := net.SplitHostPort(h) if err != nil { return h // on error, return unchanged } return host } // Handler returns the handler to use for the given request, // consulting r.Method, r.Host, and r.URL.Path. It always returns // a non-nil handler. If the path is not in its canonical form, the // handler will be an internally-generated handler that redirects // to the canonical path. If the host contains a port, it is ignored // when matching handlers. // // The path and host are used unchanged for CONNECT requests. // // Handler also returns the registered pattern that matches the // request or, in the case of internally-generated redirects, // the path that will match after following the redirect. // // If there is no registered handler that applies to the request, // Handler returns a “page not found” handler and an empty pattern. func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) { if use121 { return mux.mux121.findHandler(r) } h, p, _, _ := mux.findHandler(r) return h, p } // findHandler finds a handler for a request. // If there is a matching handler, it returns it and the pattern that matched. // Otherwise it returns a Redirect or NotFound handler with the path that would match // after the redirect. func (mux *ServeMux) findHandler(r *Request) (h Handler, patStr string, _ *pattern, matches []string) { var n *routingNode host := r.URL.Host escapedPath := r.URL.EscapedPath() path := escapedPath // CONNECT requests are not canonicalized. if r.Method == "CONNECT" { // If r.URL.Path is /tree and its handler is not registered, // the /tree -> /tree/ redirect applies to CONNECT requests // but the path canonicalization does not. _, _, u := mux.matchOrRedirect(host, r.Method, path, r.URL) if u != nil { return RedirectHandler(u.String(), StatusMovedPermanently), u.Path, nil, nil } // Redo the match, this time with r.Host instead of r.URL.Host. // Pass a nil URL to skip the trailing-slash redirect logic. n, matches, _ = mux.matchOrRedirect(r.Host, r.Method, path, nil) } else { // All other requests have any port stripped and path cleaned // before passing to mux.handler. host = stripHostPort(r.Host) path = cleanPath(path) // If the given path is /tree and its handler is not registered, // redirect for /tree/. var u *url.URL n, matches, u = mux.matchOrRedirect(host, r.Method, path, r.URL) if u != nil { return RedirectHandler(u.String(), StatusMovedPermanently), u.Path, nil, nil } if path != escapedPath { // Redirect to cleaned path. patStr := "" if n != nil { patStr = n.pattern.String() } u := &url.URL{Path: path, RawQuery: r.URL.RawQuery} return RedirectHandler(u.String(), StatusMovedPermanently), patStr, nil, nil } } if n == nil { // We didn't find a match with the request method. To distinguish between // Not Found and Method Not Allowed, see if there is another pattern that // matches except for the method. allowedMethods := mux.matchingMethods(host, path) if len(allowedMethods) > 0 { return HandlerFunc(func(w ResponseWriter, r *Request) { w.Header().Set("Allow", strings.Join(allowedMethods, ", ")) Error(w, StatusText(StatusMethodNotAllowed), StatusMethodNotAllowed) }), "", nil, nil } return NotFoundHandler(), "", nil, nil } return n.handler, n.pattern.String(), n.pattern, matches } // matchOrRedirect looks up a node in the tree that matches the host, method and path. // // If the url argument is non-nil, handler also deals with trailing-slash // redirection: when a path doesn't match exactly, the match is tried again // after appending "/" to the path. If that second match succeeds, the last // return value is the URL to redirect to. func (mux *ServeMux) matchOrRedirect(host, method, path string, u *url.URL) (_ *routingNode, matches []string, redirectTo *url.URL) { mux.mu.RLock() defer mux.mu.RUnlock() n, matches := mux.tree.match(host, method, path) // If we have an exact match, or we were asked not to try trailing-slash redirection, // or the URL already has a trailing slash, then we're done. if !exactMatch(n, path) && u != nil && !strings.HasSuffix(path, "/") { // If there is an exact match with a trailing slash, then redirect. path += "/" n2, _ := mux.tree.match(host, method, path) if exactMatch(n2, path) { return nil, nil, &url.URL{Path: cleanPath(u.Path) + "/", RawQuery: u.RawQuery} } } return n, matches, nil } // exactMatch reports whether the node's pattern exactly matches the path. // As a special case, if the node is nil, exactMatch return false. // // Before wildcards were introduced, it was clear that an exact match meant // that the pattern and path were the same string. The only other possibility // was that a trailing-slash pattern, like "/", matched a path longer than // it, like "/a". // // With wildcards, we define an inexact match as any one where a multi wildcard // matches a non-empty string. All other matches are exact. // For example, these are all exact matches: // // pattern path // /a /a // /{x} /a // /a/{$} /a/ // /a/ /a/ // // The last case has a multi wildcard (implicitly), but the match is exact because // the wildcard matches the empty string. // // Examples of matches that are not exact: // // pattern path // / /a // /a/{x...} /a/b func exactMatch(n *routingNode, path string) bool { if n == nil { return false } // We can't directly implement the definition (empty match for multi // wildcard) because we don't record a match for anonymous multis. // If there is no multi, the match is exact. if !n.pattern.lastSegment().multi { return true } // If the path doesn't end in a trailing slash, then the multi match // is non-empty. if len(path) > 0 && path[len(path)-1] != '/' { return false } // Only patterns ending in {$} or a multi wildcard can // match a path with a trailing slash. // For the match to be exact, the number of pattern // segments should be the same as the number of slashes in the path. // E.g. "/a/b/{$}" and "/a/b/{...}" exactly match "/a/b/", but "/a/" does not. return len(n.pattern.segments) == strings.Count(path, "/") } // matchingMethods return a sorted list of all methods that would match with the given host and path. func (mux *ServeMux) matchingMethods(host, path string) []string { // Hold the read lock for the entire method so that the two matches are done // on the same set of registered patterns. mux.mu.RLock() defer mux.mu.RUnlock() ms := map[string]bool{} mux.tree.matchingMethods(host, path, ms) // matchOrRedirect will try appending a trailing slash if there is no match. if !strings.HasSuffix(path, "/") { mux.tree.matchingMethods(host, path+"/", ms) } return slices.Sorted(maps.Keys(ms)) } // ServeHTTP dispatches the request to the handler whose // pattern most closely matches the request URL. func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { if r.RequestURI == "*" { if r.ProtoAtLeast(1, 1) { w.Header().Set("Connection", "close") } w.WriteHeader(StatusBadRequest) return } var h Handler if use121 { h, _ = mux.mux121.findHandler(r) } else { h, r.Pattern, r.pat, r.matches = mux.findHandler(r) } h.ServeHTTP(w, r) } // The four functions below all call ServeMux.register so that callerLocation // always refers to user code. // Handle registers the handler for the given pattern. // If the given pattern conflicts, with one that is already registered, Handle // panics. func (mux *ServeMux) Handle(pattern string, handler Handler) { if use121 { mux.mux121.handle(pattern, handler) } else { mux.register(pattern, handler) } } // HandleFunc registers the handler function for the given pattern. // If the given pattern conflicts, with one that is already registered, HandleFunc // panics. func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { if use121 { mux.mux121.handleFunc(pattern, handler) } else { mux.register(pattern, HandlerFunc(handler)) } } // Handle registers the handler for the given pattern in [DefaultServeMux]. // The documentation for [ServeMux] explains how patterns are matched. func Handle(pattern string, handler Handler) { if use121 { DefaultServeMux.mux121.handle(pattern, handler) } else { DefaultServeMux.register(pattern, handler) } } // HandleFunc registers the handler function for the given pattern in [DefaultServeMux]. // The documentation for [ServeMux] explains how patterns are matched. func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { if use121 { DefaultServeMux.mux121.handleFunc(pattern, handler) } else { DefaultServeMux.register(pattern, HandlerFunc(handler)) } } func (mux *ServeMux) register(pattern string, handler Handler) { if err := mux.registerErr(pattern, handler); err != nil { panic(err) } } func (mux *ServeMux) registerErr(patstr string, handler Handler) error { if patstr == "" { return errors.New("http: invalid pattern") } if handler == nil { return errors.New("http: nil handler") } if f, ok := handler.(HandlerFunc); ok && f == nil { return errors.New("http: nil handler") } pat, err := parsePattern(patstr) if err != nil { return fmt.Errorf("parsing %q: %w", patstr, err) } // Get the caller's location, for better conflict error messages. // Skip register and whatever calls it. _, file, line, ok := runtime.Caller(3) if !ok { pat.loc = "unknown location" } else { pat.loc = fmt.Sprintf("%s:%d", file, line) } mux.mu.Lock() defer mux.mu.Unlock() // Check for conflict. if err := mux.index.possiblyConflictingPatterns(pat, func(pat2 *pattern) error { if pat.conflictsWith(pat2) { d := describeConflict(pat, pat2) return fmt.Errorf("pattern %q (registered at %s) conflicts with pattern %q (registered at %s):\n%s", pat, pat.loc, pat2, pat2.loc, d) } return nil }); err != nil { return err } mux.tree.addPattern(pat, handler) mux.index.addPattern(pat) mux.patterns = append(mux.patterns, pat) return nil } // Serve accepts incoming HTTP connections on the listener l, // creating a new service goroutine for each. The service goroutines // read requests and then call handler to reply to them. // // The handler is typically nil, in which case [DefaultServeMux] is used. // // HTTP/2 support is only enabled if the Listener returns [*tls.Conn] // connections and they were configured with "h2" in the TLS // Config.NextProtos. // // Serve always returns a non-nil error. func Serve(l net.Listener, handler Handler) error { srv := &Server{Handler: handler} return srv.Serve(l) } // ServeTLS accepts incoming HTTPS connections on the listener l, // creating a new service goroutine for each. The service goroutines // read requests and then call handler to reply to them. // // The handler is typically nil, in which case [DefaultServeMux] is used. // // Additionally, files containing a certificate and matching private key // for the server must be provided. If the certificate is signed by a // certificate authority, the certFile should be the concatenation // of the server's certificate, any intermediates, and the CA's certificate. // // ServeTLS always returns a non-nil error. func ServeTLS(l net.Listener, handler Handler, certFile, keyFile string) error { srv := &Server{Handler: handler} return srv.ServeTLS(l, certFile, keyFile) } // A Server defines parameters for running an HTTP server. // The zero value for Server is a valid configuration. type Server struct { // Addr optionally specifies the TCP address for the server to listen on, // in the form "host:port". If empty, ":http" (port 80) is used. // The service names are defined in RFC 6335 and assigned by IANA. // See net.Dial for details of the address format. Addr string Handler Handler // handler to invoke, http.DefaultServeMux if nil // DisableGeneralOptionsHandler, if true, passes "OPTIONS *" requests to the Handler, // otherwise responds with 200 OK and Content-Length: 0. DisableGeneralOptionsHandler bool // TLSConfig optionally provides a TLS configuration for use // by ServeTLS and ListenAndServeTLS. Note that this value is // cloned by ServeTLS and ListenAndServeTLS, so it's not // possible to modify the configuration with methods like // tls.Config.SetSessionTicketKeys. To use // SetSessionTicketKeys, use Server.Serve with a TLS Listener // instead. TLSConfig *tls.Config // ReadTimeout is the maximum duration for reading the entire // request, including the body. A zero or negative value means // there will be no timeout. // // Because ReadTimeout does not let Handlers make per-request // decisions on each request body's acceptable deadline or // upload rate, most users will prefer to use // ReadHeaderTimeout. It is valid to use them both. ReadTimeout time.Duration // ReadHeaderTimeout is the amount of time allowed to read // request headers. The connection's read deadline is reset // after reading the headers and the Handler can decide what // is considered too slow for the body. If zero, the value of // ReadTimeout is used. If negative, or if zero and ReadTimeout // is zero or negative, there is no timeout. ReadHeaderTimeout time.Duration // WriteTimeout is the maximum duration before timing out // writes of the response. It is reset whenever a new // request's header is read. Like ReadTimeout, it does not // let Handlers make decisions on a per-request basis. // A zero or negative value means there will be no timeout. WriteTimeout time.Duration // IdleTimeout is the maximum amount of time to wait for the // next request when keep-alives are enabled. If zero, the value // of ReadTimeout is used. If negative, or if zero and ReadTimeout // is zero or negative, there is no timeout. IdleTimeout time.Duration // MaxHeaderBytes controls the maximum number of bytes the // server will read parsing the request header's keys and // values, including the request line. It does not limit the // size of the request body. // If zero, DefaultMaxHeaderBytes is used. MaxHeaderBytes int // TLSNextProto optionally specifies a function to take over // ownership of the provided TLS connection when an ALPN // protocol upgrade has occurred. The map key is the protocol // name negotiated. The Handler argument should be used to // 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 not nil, HTTP/2 support is not enabled // automatically. TLSNextProto map[string]func(*Server, *tls.Conn, Handler) // ConnState specifies an optional callback function that is // called when a client connection changes state. See the // ConnState type and associated constants for details. ConnState func(net.Conn, ConnState) // ErrorLog specifies an optional logger for errors accepting // connections, unexpected behavior from handlers, and // underlying FileSystem errors. // If nil, logging is done via the log package's standard logger. ErrorLog *log.Logger // BaseContext optionally specifies a function that returns // the base context for incoming requests on this server. // The provided Listener is the specific Listener that's // about to start accepting requests. // If BaseContext is nil, the default is context.Background(). // If non-nil, it must return a non-nil context. BaseContext func(net.Listener) context.Context // ConnContext optionally specifies a function that modifies // the context used for a new connection c. The provided ctx // is derived from the base context and has a ServerContextKey // value. ConnContext func(ctx context.Context, c net.Conn) context.Context inShutdown atomic.Bool // true when server is in shutdown disableKeepAlives atomic.Bool nextProtoOnce sync.Once // guards setupHTTP2_* init nextProtoErr error // result of http2.ConfigureServer if used mu sync.Mutex listeners map[*net.Listener]struct{} activeConn map[*conn]struct{} onShutdown []func() listenerGroup sync.WaitGroup } // Close immediately closes all active net.Listeners and any // connections in state [StateNew], [StateActive], or [StateIdle]. For a // graceful shutdown, use [Server.Shutdown]. // // Close does not attempt to close (and does not even know about) // any hijacked connections, such as WebSockets. // // Close returns any error returned from closing the [Server]'s // underlying Listener(s). func (srv *Server) Close() error { srv.inShutdown.Store(true) srv.mu.Lock() defer srv.mu.Unlock() err := srv.closeListenersLocked() // Unlock srv.mu while waiting for listenerGroup. // The group Add and Done calls are made with srv.mu held, // to avoid adding a new listener in the window between // us setting inShutdown above and waiting here. srv.mu.Unlock() srv.listenerGroup.Wait() srv.mu.Lock() for c := range srv.activeConn { c.rwc.Close() delete(srv.activeConn, c) } return err } // shutdownPollIntervalMax is the max polling interval when checking // quiescence during Server.Shutdown. Polling starts with a small // interval and backs off to the max. // Ideally we could find a solution that doesn't involve polling, // but which also doesn't have a high runtime cost (and doesn't // involve any contentious mutexes), but that is left as an // exercise for the reader. const shutdownPollIntervalMax = 500 * time.Millisecond // Shutdown gracefully shuts down the server without interrupting any // active connections. Shutdown works by first closing all open // listeners, then closing all idle connections, and then waiting // indefinitely for connections to return to idle and then shut down. // If the provided context expires before the shutdown is complete, // Shutdown returns the context's error, otherwise it returns any // error returned from closing the [Server]'s underlying Listener(s). // // When Shutdown is called, [Serve], [ListenAndServe], and // [ListenAndServeTLS] immediately return [ErrServerClosed]. Make sure the // program doesn't exit and waits instead for Shutdown to return. // // Shutdown does not attempt to close nor wait for hijacked // connections such as WebSockets. The caller of Shutdown should // separately notify such long-lived connections of shutdown and wait // for them to close, if desired. See [Server.RegisterOnShutdown] for a way to // register shutdown notification functions. // // Once Shutdown has been called on a server, it may not be reused; // future calls to methods such as Serve will return ErrServerClosed. func (srv *Server) Shutdown(ctx context.Context) error { srv.inShutdown.Store(true) srv.mu.Lock() lnerr := srv.closeListenersLocked() for _, f := range srv.onShutdown { go f() } srv.mu.Unlock() srv.listenerGroup.Wait() pollIntervalBase := time.Millisecond nextPollInterval := func() time.Duration { // Add 10% jitter. interval := pollIntervalBase + time.Duration(rand.Intn(int(pollIntervalBase/10))) // Double and clamp for next time. pollIntervalBase *= 2 if pollIntervalBase > shutdownPollIntervalMax { pollIntervalBase = shutdownPollIntervalMax } return interval } timer := time.NewTimer(nextPollInterval()) defer timer.Stop() for { if srv.closeIdleConns() { return lnerr } select { case <-ctx.Done(): return ctx.Err() case <-timer.C: timer.Reset(nextPollInterval()) } } } // RegisterOnShutdown registers a function to call on [Server.Shutdown]. // This can be used to gracefully shutdown connections that have // undergone ALPN protocol upgrade or that have been hijacked. // This function should start protocol-specific graceful shutdown, // but should not wait for shutdown to complete. func (srv *Server) RegisterOnShutdown(f func()) { srv.mu.Lock() srv.onShutdown = append(srv.onShutdown, f) srv.mu.Unlock() } // closeIdleConns closes all idle connections and reports whether the // server is quiescent. func (s *Server) closeIdleConns() bool { s.mu.Lock() defer s.mu.Unlock() quiescent := true for c := range s.activeConn { st, unixSec := c.getState() // Issue 22682: treat StateNew connections as if // they're idle if we haven't read the first request's // header in over 5 seconds. if st == StateNew && unixSec < time.Now().Unix()-5 { st = StateIdle } if st != StateIdle || unixSec == 0 { // Assume unixSec == 0 means it's a very new // connection, without state set yet. quiescent = false continue } c.rwc.Close() delete(s.activeConn, c) } return quiescent } func (s *Server) closeListenersLocked() error { var err error for ln := range s.listeners { if cerr := (*ln).Close(); cerr != nil && err == nil { err = cerr } } return err } // A ConnState represents the state of a client connection to a server. // It's used by the optional [Server.ConnState] hook. type ConnState int const ( // StateNew represents a new connection that is expected to // send a request immediately. Connections begin at this // state and then transition to either StateActive or // StateClosed. StateNew ConnState = iota // StateActive represents a connection that has read 1 or more // bytes of a request. The Server.ConnState hook for // StateActive fires before the request has entered a handler // 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 // cannot be used to do per-request work; ConnState only notes // the overall state of the connection. StateActive // StateIdle represents a connection that has finished // handling a request and is in the keep-alive state, waiting // for a new request. Connections transition from StateIdle // to either StateActive or StateClosed. StateIdle // StateHijacked represents a hijacked connection. // This is a terminal state. It does not transition to StateClosed. StateHijacked // StateClosed represents a closed connection. // This is a terminal state. Hijacked connections do not // transition to StateClosed. StateClosed ) var stateName = map[ConnState]string{ StateNew: "new", StateActive: "active", StateIdle: "idle", StateHijacked: "hijacked", StateClosed: "closed", } func (c ConnState) String() string { return stateName[c] } // serverHandler delegates to either the server's Handler or // DefaultServeMux and also handles "OPTIONS *" requests. type serverHandler struct { srv *Server } // ServeHTTP should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/erda-project/erda-infra // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname badServeHTTP net/http.serverHandler.ServeHTTP func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { handler := sh.srv.Handler if handler == nil { handler = DefaultServeMux } if !sh.srv.DisableGeneralOptionsHandler && req.RequestURI == "*" && req.Method == "OPTIONS" { handler = globalOptionsHandler{} } handler.ServeHTTP(rw, req) } func badServeHTTP(serverHandler, ResponseWriter, *Request) // AllowQuerySemicolons returns a handler that serves requests by converting any // unescaped semicolons in the URL query to ampersands, and invoking the handler h. // // This restores the pre-Go 1.17 behavior of splitting query parameters on both // semicolons and ampersands. (See golang.org/issue/25192). Note that this // behavior doesn't match that of many proxies, and the mismatch can lead to // security issues. // // AllowQuerySemicolons should be invoked before [Request.ParseForm] is called. func AllowQuerySemicolons(h Handler) Handler { return HandlerFunc(func(w ResponseWriter, r *Request) { if strings.Contains(r.URL.RawQuery, ";") { r2 := new(Request) *r2 = *r r2.URL = new(url.URL) *r2.URL = *r.URL r2.URL.RawQuery = strings.ReplaceAll(r.URL.RawQuery, ";", "&") h.ServeHTTP(w, r2) } else { h.ServeHTTP(w, r) } }) } // ListenAndServe listens on the TCP network address srv.Addr and then // 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. After [Server.Shutdown] or [Server.Close], // the returned error is [ErrServerClosed]. func (srv *Server) ListenAndServe() error { if srv.shuttingDown() { return ErrServerClosed } addr := srv.Addr if addr == "" { addr = ":http" } ln, err := net.Listen("tcp", addr) if err != nil { return err } return srv.Serve(ln) } var testHookServerServe func(*Server, net.Listener) // used if non-nil // shouldConfigureHTTP2ForServe reports whether Server.Serve should configure // automatic HTTP/2. (which sets up the srv.TLSNextProto map) func (srv *Server) shouldConfigureHTTP2ForServe() bool { if srv.TLSConfig == nil { // Compatibility with Go 1.6: // If there's no TLSConfig, it's possible that the user just // didn't set it on the http.Server, but did pass it to // tls.NewListener and passed that listener to Serve. // So we should configure HTTP/2 (to set up srv.TLSNextProto) // in case the listener returns an "h2" *tls.Conn. return true } // The user specified a TLSConfig on their http.Server. // In this, case, only configure HTTP/2 if their tls.Config // explicitly mentions "h2". Otherwise http2.ConfigureServer // would modify the tls.Config to add it, but they probably already // passed this tls.Config to tls.NewListener. And if they did, // it's too late anyway to fix it. It would only be potentially racy. // See Issue 15908. return slices.Contains(srv.TLSConfig.NextProtos, http2NextProtoTLS) } // ErrServerClosed is returned by the [Server.Serve], [ServeTLS], [ListenAndServe], // and [ListenAndServeTLS] methods after a call to [Server.Shutdown] or [Server.Close]. var ErrServerClosed = errors.New("http: Server closed") // Serve accepts incoming connections on the Listener l, creating a // new service goroutine for each. The service goroutines read requests and // then call srv.Handler to reply to them. // // HTTP/2 support is only enabled if the Listener returns [*tls.Conn] // connections and they were configured with "h2" in the TLS // Config.NextProtos. // // Serve always returns a non-nil error and closes l. // After [Server.Shutdown] or [Server.Close], the returned error is [ErrServerClosed]. func (srv *Server) Serve(l net.Listener) error { if fn := testHookServerServe; fn != nil { fn(srv, l) // call hook with unwrapped listener } origListener := l l = &onceCloseListener{Listener: l} defer l.Close() if err := srv.setupHTTP2_Serve(); err != nil { return err } if !srv.trackListener(&l, true) { return ErrServerClosed } defer srv.trackListener(&l, false) baseCtx := context.Background() if srv.BaseContext != nil { baseCtx = srv.BaseContext(origListener) if baseCtx == nil { panic("BaseContext returned a nil context") } } var tempDelay time.Duration // how long to sleep on accept failure ctx := context.WithValue(baseCtx, ServerContextKey, srv) for { rw, err := l.Accept() if err != nil { if srv.shuttingDown() { return ErrServerClosed } if ne, ok := err.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay) time.Sleep(tempDelay) continue } return err } connCtx := ctx if cc := srv.ConnContext; cc != nil { connCtx = cc(connCtx, rw) if connCtx == nil { panic("ConnContext returned nil") } } tempDelay = 0 c := srv.newConn(rw) c.setState(c.rwc, StateNew, runHooks) // before Serve can return go c.serve(connCtx) } } // ServeTLS accepts incoming connections on the Listener l, creating a // new service goroutine for each. The service goroutines perform TLS // setup and then read requests, calling srv.Handler to reply to them. // // Files containing a certificate and matching private key for the // server must be provided if neither the [Server]'s // TLSConfig.Certificates, TLSConfig.GetCertificate nor // config.GetConfigForClient are populated. // If the certificate is signed by a certificate authority, the // certFile should be the concatenation of the server's certificate, // any intermediates, and the CA's certificate. // // ServeTLS always returns a non-nil error. After [Server.Shutdown] or [Server.Close], the // returned error is [ErrServerClosed]. func (srv *Server) ServeTLS(l net.Listener, certFile, keyFile string) error { // Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig // before we clone it and create the TLS Listener. if err := srv.setupHTTP2_ServeTLS(); err != nil { return err } config := cloneTLSConfig(srv.TLSConfig) if !slices.Contains(config.NextProtos, "http/1.1") { config.NextProtos = append(config.NextProtos, "http/1.1") } configHasCert := len(config.Certificates) > 0 || config.GetCertificate != nil || config.GetConfigForClient != nil if !configHasCert || certFile != "" || keyFile != "" { var err error config.Certificates = make([]tls.Certificate, 1) config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return err } } tlsListener := tls.NewListener(l, config) return srv.Serve(tlsListener) } // trackListener adds or removes a net.Listener to the set of tracked // listeners. // // We store a pointer to interface in the map set, in case the // net.Listener is not comparable. This is safe because we only call // trackListener via Serve and can track+defer untrack the same // pointer to local variable there. We never need to compare a // Listener from another caller. // // It reports whether the server is still up (not Shutdown or Closed). func (s *Server) trackListener(ln *net.Listener, add bool) bool { s.mu.Lock() defer s.mu.Unlock() if s.listeners == nil { s.listeners = make(map[*net.Listener]struct{}) } if add { if s.shuttingDown() { return false } s.listeners[ln] = struct{}{} s.listenerGroup.Add(1) } else { delete(s.listeners, ln) s.listenerGroup.Done() } return true } func (s *Server) trackConn(c *conn, add bool) { s.mu.Lock() defer s.mu.Unlock() if s.activeConn == nil { s.activeConn = make(map[*conn]struct{}) } if add { s.activeConn[c] = struct{}{} } else { delete(s.activeConn, c) } } func (s *Server) idleTimeout() time.Duration { if s.IdleTimeout != 0 { return s.IdleTimeout } return s.ReadTimeout } func (s *Server) readHeaderTimeout() time.Duration { if s.ReadHeaderTimeout != 0 { return s.ReadHeaderTimeout } return s.ReadTimeout } func (s *Server) doKeepAlives() bool { return !s.disableKeepAlives.Load() && !s.shuttingDown() } func (s *Server) shuttingDown() bool { return s.inShutdown.Load() } // SetKeepAlivesEnabled controls whether HTTP keep-alives are enabled. // By default, keep-alives are always enabled. Only very // resource-constrained environments or servers in the process of // shutting down should disable them. func (srv *Server) SetKeepAlivesEnabled(v bool) { if v { srv.disableKeepAlives.Store(false) return } srv.disableKeepAlives.Store(true) // Close idle HTTP/1 conns: srv.closeIdleConns() // TODO: Issue 26303: close HTTP/2 conns as soon as they become idle. } func (s *Server) logf(format string, args ...any) { if s.ErrorLog != nil { s.ErrorLog.Printf(format, args...) } else { log.Printf(format, args...) } } // logf prints to the ErrorLog of the *Server associated with request r // via ServerContextKey. If there's no associated server, or if ErrorLog // is nil, logging is done via the log package's standard logger. func logf(r *Request, format string, args ...any) { s, _ := r.Context().Value(ServerContextKey).(*Server) if s != nil && s.ErrorLog != nil { s.ErrorLog.Printf(format, args...) } else { log.Printf(format, args...) } } // ListenAndServe listens on the TCP network address addr and then calls // [Serve] with handler to handle requests on incoming connections. // Accepted connections are configured to enable TCP keep-alives. // // The handler is typically nil, in which case [DefaultServeMux] is used. // // ListenAndServe always returns a non-nil error. func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() } // ListenAndServeTLS acts identically to [ListenAndServe], except that it // expects HTTPS connections. Additionally, files containing a certificate and // matching private key for the server must be provided. If the certificate // is signed by a certificate authority, the certFile should be the concatenation // of the server's certificate, any intermediates, and the CA's certificate. 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 [ServeTLS] 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 neither the [Server]'s TLSConfig.Certificates // nor TLSConfig.GetCertificate are populated. If the certificate is // signed by a certificate authority, the certFile should be the // concatenation of the server's certificate, any intermediates, and // the CA's certificate. // // If srv.Addr is blank, ":https" is used. // // ListenAndServeTLS always returns a non-nil error. After [Server.Shutdown] or // [Server.Close], the returned error is [ErrServerClosed]. func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { if srv.shuttingDown() { return ErrServerClosed } addr := srv.Addr if addr == "" { addr = ":https" } ln, err := net.Listen("tcp", addr) if err != nil { return err } defer ln.Close() return srv.ServeTLS(ln, certFile, keyFile) } // setupHTTP2_ServeTLS conditionally configures HTTP/2 on // srv and reports whether there was an error setting it up. If it is // not configured for policy reasons, nil is returned. func (srv *Server) setupHTTP2_ServeTLS() error { srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults) return srv.nextProtoErr } // setupHTTP2_Serve is called from (*Server).Serve and conditionally // configures HTTP/2 on srv using a more conservative policy than // setupHTTP2_ServeTLS because Serve is called after tls.Listen, // and may be called concurrently. See shouldConfigureHTTP2ForServe. // // The tests named TestTransportAutomaticHTTP2* and // TestConcurrentServerServe in server_test.go demonstrate some // of the supported use cases and motivations. func (srv *Server) setupHTTP2_Serve() error { srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults_Serve) return srv.nextProtoErr } func (srv *Server) onceSetNextProtoDefaults_Serve() { if srv.shouldConfigureHTTP2ForServe() { srv.onceSetNextProtoDefaults() } } var http2server = godebug.New("http2server") // 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 omitBundledHTTP2 { return } if http2server.Value() == "0" { http2server.IncNonDefault() return } // Enable HTTP/2 by default if the user hasn't otherwise // configured their TLSNextProto map. if srv.TLSNextProto == nil { conf := &http2Server{} srv.nextProtoErr = http2ConfigureServer(srv, conf) } } // 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 // call runs for longer than its time limit, the handler responds with // a 503 Service Unavailable error and the given message in its body. // (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 supports the [Pusher] interface but does not support // the [Hijacker] or [Flusher] interfaces. func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler { return &timeoutHandler{ handler: h, body: msg, dt: dt, } } // ErrHandlerTimeout is returned on [ResponseWriter] Write calls // in handlers which have timed out. var ErrHandlerTimeout = errors.New("http: Handler timeout") type timeoutHandler struct { handler Handler body string dt time.Duration // When set, no context will be created and this context will // be used instead. testContext context.Context } func (h *timeoutHandler) errorBody() string { if h.body != "" { return h.body } return "Timeout

Timeout

" } func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) { ctx := h.testContext if ctx == nil { var cancelCtx context.CancelFunc ctx, cancelCtx = context.WithTimeout(r.Context(), h.dt) defer cancelCtx() } r = r.WithContext(ctx) done := make(chan struct{}) tw := &timeoutWriter{ w: w, h: make(Header), req: r, } panicChan := make(chan any, 1) go func() { defer func() { if p := recover(); p != nil { panicChan <- p } }() h.handler.ServeHTTP(tw, r) close(done) }() select { case p := <-panicChan: panic(p) case <-done: tw.mu.Lock() defer tw.mu.Unlock() dst := w.Header() for k, vv := range tw.h { dst[k] = vv } if !tw.wroteHeader { tw.code = StatusOK } w.WriteHeader(tw.code) w.Write(tw.wbuf.Bytes()) case <-ctx.Done(): tw.mu.Lock() defer tw.mu.Unlock() switch err := ctx.Err(); err { case context.DeadlineExceeded: w.WriteHeader(StatusServiceUnavailable) io.WriteString(w, h.errorBody()) tw.err = ErrHandlerTimeout default: w.WriteHeader(StatusServiceUnavailable) tw.err = err } } } type timeoutWriter struct { w ResponseWriter h Header wbuf bytes.Buffer req *Request mu sync.Mutex err error wroteHeader bool code int } var _ Pusher = (*timeoutWriter)(nil) // Push implements the [Pusher] interface. func (tw *timeoutWriter) Push(target string, opts *PushOptions) error { if pusher, ok := tw.w.(Pusher); ok { return pusher.Push(target, opts) } return ErrNotSupported } func (tw *timeoutWriter) Header() Header { return tw.h } func (tw *timeoutWriter) Write(p []byte) (int, error) { tw.mu.Lock() defer tw.mu.Unlock() if tw.err != nil { return 0, tw.err } if !tw.wroteHeader { tw.writeHeaderLocked(StatusOK) } return tw.wbuf.Write(p) } func (tw *timeoutWriter) writeHeaderLocked(code int) { checkWriteHeaderCode(code) switch { case tw.err != nil: return case tw.wroteHeader: if tw.req != nil { caller := relevantCaller() logf(tw.req, "http: superfluous response.WriteHeader call from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line) } default: tw.wroteHeader = true tw.code = code } } func (tw *timeoutWriter) WriteHeader(code int) { tw.mu.Lock() defer tw.mu.Unlock() tw.writeHeaderLocked(code) } // onceCloseListener wraps a net.Listener, protecting it from // multiple Close calls. type onceCloseListener struct { net.Listener once sync.Once closeErr error } func (oc *onceCloseListener) Close() error { oc.once.Do(oc.close) return oc.closeErr } func (oc *onceCloseListener) close() { oc.closeErr = oc.Listener.Close() } // globalOptionsHandler responds to "OPTIONS *" requests. type globalOptionsHandler struct{} func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) { w.Header().Set("Content-Length", "0") if r.ContentLength != 0 { // Read up to 4KB of OPTIONS body (as mentioned in the // spec as being reserved for future use), but anything // over that is considered a waste of server resources // (or an attack) and we abort and close the connection, // courtesy of MaxBytesReader's EOF behavior. mb := MaxBytesReader(w, r.Body, 4<<10) io.Copy(io.Discard, mb) } } // initALPNRequest is an HTTP handler that initializes certain // uninitialized fields in its *Request. Such partially-initialized // Requests come from ALPN protocol handlers. type initALPNRequest struct { ctx context.Context c *tls.Conn h serverHandler } // BaseContext is an exported but unadvertised [http.Handler] method // recognized by x/net/http2 to pass down a context; the TLSNextProto // API predates context support so we shoehorn through the only // interface we have available. func (h initALPNRequest) BaseContext() context.Context { return h.ctx } func (h initALPNRequest) ServeHTTP(rw ResponseWriter, req *Request) { if req.TLS == nil { req.TLS = &tls.ConnectionState{} *req.TLS = h.c.ConnectionState() } if req.Body == nil { req.Body = NoBody } if req.RemoteAddr == "" { req.RemoteAddr = h.c.RemoteAddr().String() } h.h.ServeHTTP(rw, req) } // loggingConn is used for debugging. type loggingConn struct { name string net.Conn } var ( uniqNameMu sync.Mutex uniqNameNext = make(map[string]int) ) func newLoggingConn(baseName string, c net.Conn) net.Conn { uniqNameMu.Lock() defer uniqNameMu.Unlock() uniqNameNext[baseName]++ return &loggingConn{ name: fmt.Sprintf("%s-%d", baseName, uniqNameNext[baseName]), Conn: c, } } func (c *loggingConn) Write(p []byte) (n int, err error) { log.Printf("%s.Write(%d) = ....", c.name, len(p)) n, err = c.Conn.Write(p) log.Printf("%s.Write(%d) = %d, %v", c.name, len(p), n, err) return } func (c *loggingConn) Read(p []byte) (n int, err error) { log.Printf("%s.Read(%d) = ....", c.name, len(p)) n, err = c.Conn.Read(p) log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err) return } func (c *loggingConn) Close() (err error) { log.Printf("%s.Close() = ...", c.name) err = c.Conn.Close() log.Printf("%s.Close() = %v", c.name, err) return } // checkConnErrorWriter writes to c.rwc and records any write errors to c.werr. // It only contains one field (and a pointer field at that), so it // fits in an interface value without an extra allocation. type checkConnErrorWriter struct { c *conn } func (w checkConnErrorWriter) Write(p []byte) (n int, err error) { n, err = w.c.rwc.Write(p) if err != nil && w.c.werr == nil { w.c.werr = err w.c.cancelCtx() } return } func numLeadingCRorLF(v []byte) (n int) { for _, b := range v { if b == '\r' || b == '\n' { n++ continue } break } return } // tlsRecordHeaderLooksLikeHTTP reports whether a TLS record header // looks like it might've been a misdirected plaintext HTTP request. func tlsRecordHeaderLooksLikeHTTP(hdr [5]byte) bool { switch string(hdr[:]) { case "GET /", "HEAD ", "POST ", "PUT /", "OPTIO": return true } return false } // MaxBytesHandler returns a [Handler] that runs h with its [ResponseWriter] and [Request.Body] wrapped by a MaxBytesReader. func MaxBytesHandler(h Handler, n int64) Handler { return HandlerFunc(func(w ResponseWriter, r *Request) { r2 := *r r2.Body = MaxBytesReader(w, r.Body, n) h.ServeHTTP(w, &r2) }) }