package nhttp import ( "bufio" "fmt" "log" "net" _http "net/http" "path" "runtime" "strconv" "strings" "time" ) const TrailerPrefix = "Trailer:" func fixPragmaCacheControl(header _http.Header) { if hp, ok := header["Pragma"]; ok && len(hp) > 0 && hp[0] == "no-cache" { if _, presentcc := header["Cache-Control"]; !presentcc { header["Cache-Control"] = []string{"no-cache"} } } } func (w *response) finalTrailers() _http.Header { var t _http.Header for k, vv := range w.handlerHeader { if strings.HasPrefix(k, TrailerPrefix) { if t == nil { t = make(_http.Header) } t[strings.TrimPrefix(k, TrailerPrefix)] = vv } } for _, k := range w.trailers { if t == nil { t = make(_http.Header) } for _, v := range w.handlerHeader[k] { t.Add(k, v) } } return t } 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(_http.StatusExpectationFailed) w.finishRequest() } func (w *response) finishRequest() { w.handlerDone.setTrue() if !w.wroteHeader { w.WriteHeader(_http.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() } } func (w *response) Header() _http.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 } func (w *response) WriteHeader(code int) { if w.wroteHeader { caller := relevantCaller() log.Printf("nhttp: superfluous response.WriteHeader call from %s (%s:%d)\n", caller.Function, path.Base(caller.File), caller.Line) return } checkWriteHeaderCode(code) // Handle informational headers if code >= 100 && code <= 199 { // Prevent a potential race with an automatically-sent 100 Continue triggered by Request.Body.Read() if code == 100 && w.canWriteContinue.isSet() { w.writeContinueMu.Lock() w.canWriteContinue.setFalse() w.writeContinueMu.Unlock() } writeStatusLine(w.conn.bufw, w.req.ProtoAtLeast(1, 1), code, w.statusBuf[:]) // Per RFC 8297 we must not clear the current header map w.handlerHeader.WriteSubset(w.conn.bufw, map[string]bool{"Content-Length": true, "Transfer-Encoding": true}) 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 { log.Printf("nhttp: invalid Content-Length of %q\n", cl) w.handlerHeader.Del("Content-Length") } } } // relevantCaller searches the call stack for the first function outside of net/nhttp. // 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/nhttp.") { return frame } if !more { break } } return frame } 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)) } } // 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 := _http.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) } } 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.canWriteContinue.isSet() { // Body reader wants to write 100 Continue but hasn't yet. // Tell it not to. The store must be done while holding the lock // because the lock makes sure that there is not an active write // this very moment. w.writeContinueMu.Lock() w.canWriteContinue.setFalse() w.writeContinueMu.Unlock() } if !w.wroteHeader { w.WriteHeader(_http.StatusOK) } if lenData == 0 { return 0, nil } /*if !w.bodyAllowed() { return 0, _http.ErrBodyNotAllowed }*/ w.written += int64(lenData) // ignoring errors, for errorKludge if w.contentLength != -1 && w.written > w.contentLength { return 0, _http.ErrContentLength } if dataB != nil { return w.w.Write(dataB) } else { return w.w.WriteString(dataS) } } // 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.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() } // 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). const rstAvoidanceDelay = 500 * time.Millisecond type closeWriter interface { CloseWrite() error } var _ closeWriter = (*net.TCPConn)(nil) // closeWrite 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() } time.Sleep(rstAvoidanceDelay) }