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.

package http

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	
)
ErrLineTooLong is returned when reading request or response bodies with malformed chunked encoding.
var ErrLineTooLong = internal.ErrLineTooLong

type errorReader struct {
	err error
}

func ( errorReader) ( []byte) ( int,  error) {
	return 0, .err
}

type byteReader struct {
	b    byte
	done bool
}

func ( *byteReader) ( []byte) ( int,  error) {
	if .done {
		return 0, io.EOF
	}
	if len() == 0 {
		return 0, nil
	}
	.done = true
	[0] = .b
	return 1, io.EOF
}
transferWriter inspects the fields of a user-supplied Request or Response, sanitizes them without changing the user object and provides methods for writing the respective header, body and trailer in wire format.
type transferWriter struct {
	Method           string
	Body             io.Reader
	BodyCloser       io.Closer
	ResponseToHEAD   bool
	ContentLength    int64 // -1 means unknown, 0 means exactly none
	Close            bool
	TransferEncoding []string
	Header           Header
	Trailer          Header
	IsResponse       bool
	bodyReadError    error // any non-EOF error from reading Body

	FlushHeaders bool            // flush headers to network before body
	ByteReadCh   chan readResult // non-nil if probeRequestBody called
}

func ( interface{}) ( *transferWriter,  error) {
	 = &transferWriter{}
Extract relevant fields
	 := false
	switch rr := .(type) {
	case *Request:
		if .ContentLength != 0 && .Body == nil {
			return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", .ContentLength)
		}
		.Method = valueOrDefault(.Method, "GET")
		.Close = .Close
		.TransferEncoding = .TransferEncoding
		.Header = .Header
		.Trailer = .Trailer
		.Body = .Body
		.BodyCloser = .Body
		.ContentLength = .outgoingLength()
		if .ContentLength < 0 && len(.TransferEncoding) == 0 && .shouldSendChunkedRequestBody() {
			.TransferEncoding = []string{"chunked"}
If there's a body, conservatively flush the headers to any bufio.Writer we're writing to, just in case the server needs the headers early, before we copy the body and possibly block. We make an exception for the common standard library in-memory types, though, to avoid unnecessary TCP packets on the wire. (Issue 22088.)
		if .ContentLength != 0 && !isKnownInMemoryReader(.Body) {
			.FlushHeaders = true
		}

		 = true // Transport requests are always 1.1 or 2.0
	case *Response:
		.IsResponse = true
		if .Request != nil {
			.Method = .Request.Method
		}
		.Body = .Body
		.BodyCloser = .Body
		.ContentLength = .ContentLength
		.Close = .Close
		.TransferEncoding = .TransferEncoding
		.Header = .Header
		.Trailer = .Trailer
		 = .ProtoAtLeast(1, 1)
		.ResponseToHEAD = noResponseBodyExpected(.Method)
	}
Sanitize Body,ContentLength,TransferEncoding
	if .ResponseToHEAD {
		.Body = nil
		if chunked(.TransferEncoding) {
			.ContentLength = -1
		}
	} else {
		if ! || .Body == nil {
			.TransferEncoding = nil
		}
		if chunked(.TransferEncoding) {
			.ContentLength = -1
		} else if .Body == nil { // no chunking, no body
			.ContentLength = 0
		}
	}
Sanitize Trailer
	if !chunked(.TransferEncoding) {
		.Trailer = nil
	}

	return , nil
}
shouldSendChunkedRequestBody reports whether we should try to send a chunked request body to the server. In particular, the case we really want to prevent is sending a GET or other typically-bodyless request to a server with a chunked body when the body has zero bytes, since GETs with bodies (while acceptable according to specs), even zero-byte chunked bodies, are approximately never seen in the wild and confuse most servers. See Issue 18257, as one example. The only reason we'd send such a request is if the user set the Body to a non-nil value (say, io.NopCloser(bytes.NewReader(nil))) and didn't set ContentLength, or NewRequest set it to -1 (unknown), so then we assume there's bytes to send. This code tries to read a byte from the Request.Body in such cases to see whether the body actually has content (super rare) or is actually just a non-nil content-less ReadCloser (the more common case). In that more common case, we act as if their Body were nil instead, and don't send a body.
Note that t.ContentLength is the corrected content length from rr.outgoingLength, so 0 actually means zero, not unknown.
	if .ContentLength >= 0 || .Body == nil { // redundant checks; caller did them
		return false
	}
	if .Method == "CONNECT" {
		return false
	}
Only probe the Request.Body for GET/HEAD/DELETE/etc requests, because it's only those types of requests that confuse servers.
		.probeRequestBody() // adjusts t.Body, t.ContentLength
		return .Body != nil
For all other request types (PUT, POST, PATCH, or anything made-up we've never heard of), assume it's normal and the server can deal with a chunked request body. Maybe we'll adjust this later.
	return true
}
probeRequestBody reads a byte from t.Body to see whether it's empty (returns io.EOF right away). But because we've had problems with this blocking users in the past (issue 17480) when the body is a pipe (perhaps waiting on the response headers before the pipe is fed data), we need to be careful and bound how long we wait for it. This delay will only affect users if all the following are true: * the request body blocks * the content length is not set (or set to -1) * the method doesn't usually have a body (GET, HEAD, DELETE, ...) * there is no transfer-encoding=chunked already set. In other words, this delay will not normally affect anybody, and there are workarounds if it does.
func ( *transferWriter) () {
	.ByteReadCh = make(chan readResult, 1)
	go func( io.Reader) {
		var  [1]byte
		var  readResult
		.n, .err = .Read([:])
		if .n == 1 {
			.b = [0]
		}
		.ByteReadCh <- 
	}(.Body)
	 := time.NewTimer(200 * time.Millisecond)
	select {
	case  := <-.ByteReadCh:
		.Stop()
It was empty.
			.Body = nil
			.ContentLength = 0
		} else if .n == 1 {
			if .err != nil {
				.Body = io.MultiReader(&byteReader{b: .b}, errorReader{.err})
			} else {
				.Body = io.MultiReader(&byteReader{b: .b}, .Body)
			}
		} else if .err != nil {
			.Body = errorReader{.err}
		}
Too slow. Don't wait. Read it later, and keep assuming that this is ContentLength == -1 (unknown), which means we'll send a "Transfer-Encoding: chunked" header.
Request that Request.Write flush the headers to the network before writing the body, since our body may not become readable until it's seen the response headers.
		.FlushHeaders = true
	}
}

func ( string) bool {
	return  == "HEAD"
}

func ( *transferWriter) () bool {
	if chunked(.TransferEncoding) {
		return false
	}
	if .ContentLength > 0 {
		return true
	}
	if .ContentLength < 0 {
		return false
Many servers expect a Content-Length for these methods
	if .Method == "POST" || .Method == "PUT" || .Method == "PATCH" {
		return true
	}
	if .ContentLength == 0 && isIdentity(.TransferEncoding) {
		if .Method == "GET" || .Method == "HEAD" {
			return false
		}
		return true
	}

	return false
}

func ( *transferWriter) ( io.Writer,  *httptrace.ClientTrace) error {
	if .Close && !hasToken(.Header.get("Connection"), "close") {
		if ,  := io.WriteString(, "Connection: close\r\n");  != nil {
			return 
		}
		if  != nil && .WroteHeaderField != nil {
			.WroteHeaderField("Connection", []string{"close"})
		}
	}
Write Content-Length and/or Transfer-Encoding whose values are a function of the sanitized field triple (Body, ContentLength, TransferEncoding)
	if .shouldSendContentLength() {
		if ,  := io.WriteString(, "Content-Length: ");  != nil {
			return 
		}
		if ,  := io.WriteString(, strconv.FormatInt(.ContentLength, 10)+"\r\n");  != nil {
			return 
		}
		if  != nil && .WroteHeaderField != nil {
			.WroteHeaderField("Content-Length", []string{strconv.FormatInt(.ContentLength, 10)})
		}
	} else if chunked(.TransferEncoding) {
		if ,  := io.WriteString(, "Transfer-Encoding: chunked\r\n");  != nil {
			return 
		}
		if  != nil && .WroteHeaderField != nil {
			.WroteHeaderField("Transfer-Encoding", []string{"chunked"})
		}
	}
Write Trailer header
	if .Trailer != nil {
		 := make([]string, 0, len(.Trailer))
		for  := range .Trailer {
			 = CanonicalHeaderKey()
			switch  {
			case "Transfer-Encoding", "Trailer", "Content-Length":
				return badStringError("invalid Trailer key", )
			}
			 = append(, )
		}
		if len() > 0 {
TODO: could do better allocation-wise here, but trailers are rare, so being lazy for now.
			if ,  := io.WriteString(, "Trailer: "+strings.Join(, ",")+"\r\n");  != nil {
				return 
			}
			if  != nil && .WroteHeaderField != nil {
				.WroteHeaderField("Trailer", )
			}
		}
	}

	return nil
}
always closes t.BodyCloser
func ( *transferWriter) ( io.Writer) ( error) {
	var  int64
	 := false
	defer func() {
		if  || .BodyCloser == nil {
			return
		}
		if  := .BodyCloser.Close();  != nil &&  == nil {
			 = 
		}
	}()
Write body. We "unwrap" the body first if it was wrapped in a nopCloser or readTrackingBody. This is to ensure that we can take advantage of OS-level optimizations in the event that the body is an *os.File.
	if .Body != nil {
		var  = .unwrapBody()
		if chunked(.TransferEncoding) {
			if ,  := .(*bufio.Writer);  && !.IsResponse {
				 = &internal.FlushAfterChunkWriter{Writer: }
			}
			 := internal.NewChunkedWriter()
			_,  = .doBodyCopy(, )
			if  == nil {
				 = .Close()
			}
		} else if .ContentLength == -1 {
			 := 
			if .Method == "CONNECT" {
				 = bufioFlushWriter{}
			}
			,  = .doBodyCopy(, )
		} else {
			,  = .doBodyCopy(, io.LimitReader(, .ContentLength))
			if  != nil {
				return 
			}
			var  int64
			,  = .doBodyCopy(io.Discard, )
			 += 
		}
		if  != nil {
			return 
		}
	}
	if .BodyCloser != nil {
		 = true
		if  := .BodyCloser.Close();  != nil {
			return 
		}
	}

	if !.ResponseToHEAD && .ContentLength != -1 && .ContentLength !=  {
		return fmt.Errorf("http: ContentLength=%d with Body length %d",
			.ContentLength, )
	}

Write Trailer header
		if .Trailer != nil {
			if  := .Trailer.Write();  != nil {
				return 
			}
Last chunk, empty trailer
		_,  = io.WriteString(, "\r\n")
	}
	return 
}
doBodyCopy wraps a copy operation, with any resulting error also being saved in bodyReadError. This function is only intended for use in writeBody.
func ( *transferWriter) ( io.Writer,  io.Reader) ( int64,  error) {
	,  = io.Copy(, )
	if  != nil &&  != io.EOF {
		.bodyReadError = 
	}
	return
}
unwrapBodyReader unwraps the body's inner reader if it's a nopCloser. This is to ensure that body writes sourced from local files (*os.File types) are properly optimized. This function is only intended for use in writeBody.
func ( *transferWriter) () io.Reader {
	if reflect.TypeOf(.Body) == nopCloserType {
		return reflect.ValueOf(.Body).Field(0).Interface().(io.Reader)
	}
	if ,  := .Body.(*readTrackingBody);  {
		.didRead = true
		return .ReadCloser
	}
	return .Body
}

bodyAllowedForStatus reports whether a given response status code permits a body. See RFC 7230, section 3.3.
func ( int) bool {
	switch {
	case  >= 100 &&  <= 199:
		return false
	case  == 204:
		return false
	case  == 304:
		return false
	}
	return true
}

var (
	suppressedHeaders304    = []string{"Content-Type", "Content-Length", "Transfer-Encoding"}
	suppressedHeadersNoBody = []string{"Content-Length", "Transfer-Encoding"}
)

func ( int) []string {
	switch {
RFC 7232 section 4.1
		return suppressedHeaders304
	case !bodyAllowedForStatus():
		return suppressedHeadersNoBody
	}
	return nil
}
msg is *Request or *Response.
func ( interface{},  *bufio.Reader) ( error) {
	 := &transferReader{RequestMethod: "GET"}
Unify input
	 := false
	switch rr := .(type) {
	case *Response:
		.Header = .Header
		.StatusCode = .StatusCode
		.ProtoMajor = .ProtoMajor
		.ProtoMinor = .ProtoMinor
		.Close = shouldClose(.ProtoMajor, .ProtoMinor, .Header, true)
		 = true
		if .Request != nil {
			.RequestMethod = .Request.Method
		}
	case *Request:
		.Header = .Header
		.RequestMethod = .Method
		.ProtoMajor = .ProtoMajor
Transfer semantics for Requests are exactly like those for Responses with status code 200, responding to a GET method
		.StatusCode = 200
		.Close = .Close
	default:
		panic("unexpected type")
	}
Default to HTTP/1.1
	if .ProtoMajor == 0 && .ProtoMinor == 0 {
		.ProtoMajor, .ProtoMinor = 1, 1
	}
Transfer-Encoding: chunked, and overriding Content-Length.
	if  := .parseTransferEncoding();  != nil {
		return 
	}

	,  := fixLength(, .StatusCode, .RequestMethod, .Header, .Chunked)
	if  != nil {
		return 
	}
	if  && .RequestMethod == "HEAD" {
		if ,  := parseContentLength(.Header.get("Content-Length"));  != nil {
			return 
		} else {
			.ContentLength = 
		}
	} else {
		.ContentLength = 
	}
Trailer
	.Trailer,  = fixTrailer(.Header, .Chunked)
	if  != nil {
		return 
	}
If there is no Content-Length or chunked Transfer-Encoding on a *Response and the status is not 1xx, 204 or 304, then the body is unbounded. See RFC 7230, section 3.3.
	switch .(type) {
	case *Response:
Unbounded body.
			.Close = true
		}
	}
Prepare body reader. ContentLength < 0 means chunked encoding or close connection when finished, since multipart is not supported yet
	switch {
	case .Chunked:
		if noResponseBodyExpected(.RequestMethod) || !bodyAllowedForStatus(.StatusCode) {
			.Body = NoBody
		} else {
			.Body = &body{src: internal.NewChunkedReader(), hdr: , r: , closing: .Close}
		}
	case  == 0:
		.Body = NoBody
	case  > 0:
		.Body = &body{src: io.LimitReader(, ), closing: .Close}
realLength < 0, i.e. "Content-Length" not mentioned in header
Close semantics (i.e. HTTP/1.0)
			.Body = &body{src: , closing: .Close}
Persistent connection (i.e. HTTP/1.1)
			.Body = NoBody
		}
	}
Unify output
	switch rr := .(type) {
	case *Request:
		.Body = .Body
		.ContentLength = .ContentLength
		if .Chunked {
			.TransferEncoding = []string{"chunked"}
		}
		.Close = .Close
		.Trailer = .Trailer
	case *Response:
		.Body = .Body
		.ContentLength = .ContentLength
		if .Chunked {
			.TransferEncoding = []string{"chunked"}
		}
		.Close = .Close
		.Trailer = .Trailer
	}

	return nil
}
Checks whether chunked is part of the encodings stack
func ( []string) bool { return len() > 0 && [0] == "chunked" }
Checks whether the encoding is explicitly "identity".
func ( []string) bool { return len() == 1 && [0] == "identity" }
unsupportedTEError reports unsupported transfer-encodings.
type unsupportedTEError struct {
	err string
}

func ( *unsupportedTEError) () string {
	return .err
}
isUnsupportedTEError checks if the error is of type unsupportedTEError. It is usually invoked with a non-nil err.
func ( error) bool {
	,  := .(*unsupportedTEError)
	return 
}
parseTransferEncoding sets t.Chunked based on the Transfer-Encoding header.
func ( *transferReader) () error {
	,  := .Header["Transfer-Encoding"]
	if ! {
		return nil
	}
	delete(.Header, "Transfer-Encoding")
Issue 12785; ignore Transfer-Encoding on HTTP/1.0 requests.
	if !.protoAtLeast(1, 1) {
		return nil
	}
Like nginx, we only support a single Transfer-Encoding header field, and only if set to "chunked". This is one of the most security sensitive surfaces in HTTP/1.1 due to the risk of request smuggling, so we keep it strict and simple.
	if len() != 1 {
		return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", )}
	}
	if strings.ToLower(textproto.TrimString([0])) != "chunked" {
		return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", [0])}
	}
RFC 7230 3.3.2 says "A sender MUST NOT send a Content-Length header field in any message that contains a Transfer-Encoding header field." but also: "If a message is received with both a Transfer-Encoding and a Content-Length header field, the Transfer-Encoding overrides the Content-Length. Such a message might indicate an attempt to perform request smuggling (Section 9.5) or response splitting (Section 9.4) and ought to be handled as an error. A sender MUST remove the received Content-Length field prior to forwarding such a message downstream." Reportedly, these appear in the wild.
	delete(.Header, "Content-Length")

	.Chunked = true
	return nil
}
Determine the expected body length, using RFC 7230 Section 3.3. This function is not a method, because ultimately it should be shared by ReadResponse and ReadRequest.
func ( bool,  int,  string,  Header,  bool) (int64, error) {
	 := !
	 := ["Content-Length"]
Hardening against HTTP request smuggling
Per RFC 7230 Section 3.3.2, prevent multiple Content-Length headers if they differ in value. If there are dups of the value, remove the dups. See Issue 16490.
		 := textproto.TrimString([0])
		for ,  := range [1:] {
			if  != textproto.TrimString() {
				return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", )
			}
		}
deduplicate Content-Length
		.Del("Content-Length")
		.Add("Content-Length", )

		 = ["Content-Length"]
	}
Logic based on response type or status
For HTTP requests, as part of hardening against request smuggling (RFC 7230), don't allow a Content-Length header for methods which don't permit bodies. As an exception, allow exactly one Content-Length header if its value is "0".
		if  && len() > 0 && !(len() == 1 && [0] == "0") {
			return 0, fmt.Errorf("http: method cannot contain a Content-Length; got %q", )
		}
		return 0, nil
	}
	if /100 == 1 {
		return 0, nil
	}
	switch  {
	case 204, 304:
		return 0, nil
	}
Logic based on Transfer-Encoding
	if  {
		return -1, nil
	}
Logic based on Content-Length
	var  string
	if len() == 1 {
		 = textproto.TrimString([0])
	}
	if  != "" {
		,  := parseContentLength()
		if  != nil {
			return -1, 
		}
		return , nil
	}
	.Del("Content-Length")

RFC 7230 neither explicitly permits nor forbids an entity-body on a GET request so we permit one if declared, but we default to 0 here (not -1 below) if there's no mention of a body. Likewise, all other request methods are assumed to have no body if neither Transfer-Encoding chunked nor a Content-Length are set.
		return 0, nil
	}
Body-EOF logic based on other methods (like closing, or chunked coding)
	return -1, nil
}
Determine whether to hang up after sending a request and body, or receiving a response and body 'header' is the request headers
func (,  int,  Header,  bool) bool {
	if  < 1 {
		return true
	}

	 := ["Connection"]
	 := httpguts.HeaderValuesContainsToken(, "close")
	if  == 1 &&  == 0 {
		return  || !httpguts.HeaderValuesContainsToken(, "keep-alive")
	}

	if  &&  {
		.Del("Connection")
	}

	return 
}
Parse the trailer header
func ( Header,  bool) (Header, error) {
	,  := ["Trailer"]
	if ! {
		return nil, nil
	}
Trailer and no chunking: this is an invalid use case for trailer header. Nevertheless, no error will be returned and we let users decide if this is a valid HTTP message. The Trailer header will be kept in Response.Header but not populate Response.Trailer. See issue #27197.
		return nil, nil
	}
	.Del("Trailer")

	 := make(Header)
	var  error
	for ,  := range  {
		foreachHeaderElement(, func( string) {
			 = CanonicalHeaderKey()
			switch  {
			case "Transfer-Encoding", "Trailer", "Content-Length":
				if  == nil {
					 = badStringError("bad trailer key", )
					return
				}
			}
			[] = nil
		})
	}
	if  != nil {
		return nil, 
	}
	if len() == 0 {
		return nil, nil
	}
	return , nil
}
body turns a Reader into a ReadCloser. Close ensures that the body has been fully read and then reads the trailer if necessary.
type body struct {
	src          io.Reader
	hdr          interface{}   // non-nil (Response or Request) value means read trailer
	r            *bufio.Reader // underlying wire-format reader for the trailer
	closing      bool          // is the connection to be closed after reading body?
	doEarlyClose bool          // whether Close should stop early

	mu         sync.Mutex // guards following, and calls to Read and Close
	sawEOF     bool
	closed     bool
	earlyClose bool   // Close called and we didn't read to the end of src
	onHitEOF   func() // if non-nil, func to call when EOF is Read
}
ErrBodyReadAfterClose is returned when reading a Request or Response Body after the body has been closed. This typically happens when the body is read after an HTTP Handler calls WriteHeader or Write on its ResponseWriter.
var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")

func ( *body) ( []byte) ( int,  error) {
	.mu.Lock()
	defer .mu.Unlock()
	if .closed {
		return 0, ErrBodyReadAfterClose
	}
	return .readLocked()
}
Must hold b.mu.
func ( *body) ( []byte) ( int,  error) {
	if .sawEOF {
		return 0, io.EOF
	}
	,  = .src.Read()

	if  == io.EOF {
Chunked case. Read the trailer.
		if .hdr != nil {
			if  := .readTrailer();  != nil {
Something went wrong in the trailer, we must not allow any further reads of any kind to succeed from body, nor any subsequent requests on the server connection. See golang.org/issue/12027
				.sawEOF = false
				.closed = true
			}
			.hdr = nil
If the server declared the Content-Length, our body is a LimitedReader and we need to check whether this EOF arrived early.
			if ,  := .src.(*io.LimitedReader);  && .N > 0 {
				 = io.ErrUnexpectedEOF
			}
		}
	}
If we can return an EOF here along with the read data, do so. This is optional per the io.Reader contract, but doing so helps the HTTP transport code recycle its connection earlier (since it will see this EOF itself), even if the client doesn't do future reads or Close.
	if  == nil &&  > 0 {
		if ,  := .src.(*io.LimitedReader);  && .N == 0 {
			 = io.EOF
			.sawEOF = true
		}
	}

	if .sawEOF && .onHitEOF != nil {
		.onHitEOF()
	}

	return , 
}

var (
	singleCRLF = []byte("\r\n")
	doubleCRLF = []byte("\r\n\r\n")
)

func ( *bufio.Reader) bool {
This loop stops when Peek returns an error, which it does when r's buffer has been filled.
		,  := .Peek()
		if bytes.HasSuffix(, doubleCRLF) {
			return true
		}
		if  != nil {
			break
		}
	}
	return false
}

var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")

The common case, since nobody uses trailers.
	,  := .r.Peek(2)
	if bytes.Equal(, singleCRLF) {
		.r.Discard(2)
		return nil
	}
	if len() < 2 {
		return errTrailerEOF
	}
	if  != nil {
		return 
	}
Make sure there's a header terminator coming up, to prevent a DoS with an unbounded size Trailer. It's not easy to slip in a LimitReader here, as textproto.NewReader requires a concrete *bufio.Reader. Also, we can't get all the way back up to our conn's LimitedReader that *might* be backing this bufio.Reader. Instead, a hack: we iteratively Peek up to the bufio.Reader's max size, looking for a double CRLF. This limits the trailer to the underlying buffer size, typically 4kB.
	if !seeUpcomingDoubleCRLF(.r) {
		return errors.New("http: suspiciously long trailer after chunked body")
	}

	,  := textproto.NewReader(.r).ReadMIMEHeader()
	if  != nil {
		if  == io.EOF {
			return errTrailerEOF
		}
		return 
	}
	switch rr := .hdr.(type) {
	case *Request:
		mergeSetHeader(&.Trailer, Header())
	case *Response:
		mergeSetHeader(&.Trailer, Header())
	}
	return nil
}

func ( *Header,  Header) {
	if * == nil {
		* = 
		return
	}
	for ,  := range  {
		(*)[] = 
	}
}
unreadDataSizeLocked returns the number of bytes of unread input. It returns -1 if unknown. b.mu must be held.
func ( *body) () int64 {
	if ,  := .src.(*io.LimitedReader);  {
		return .N
	}
	return -1
}

func ( *body) () error {
	.mu.Lock()
	defer .mu.Unlock()
	if .closed {
		return nil
	}
	var  error
	switch {
Already saw EOF, so no need going to look for it.
no trailer and closing the connection next. no point in reading to EOF.
Read up to maxPostHandlerReadBytes bytes of the body, looking for EOF (and trailers), so we can re-use this connection.
There was a declared Content-Length, and we have more bytes remaining than our maxPostHandlerReadBytes tolerance. So, give up.
			.earlyClose = true
		} else {
Consume the body, or, which will also lead to us reading the trailer headers after the body, if present.
			,  = io.CopyN(io.Discard, bodyLocked{}, maxPostHandlerReadBytes)
			if  == io.EOF {
				 = nil
			}
			if  == maxPostHandlerReadBytes {
				.earlyClose = true
			}
		}
Fully consume the body, which will also lead to us reading the trailer headers after the body, if present.
		_,  = io.Copy(io.Discard, bodyLocked{})
	}
	.closed = true
	return 
}

func ( *body) () bool {
	.mu.Lock()
	defer .mu.Unlock()
	return .earlyClose
}
bodyRemains reports whether future Read calls might yield data.
func ( *body) () bool {
	.mu.Lock()
	defer .mu.Unlock()
	return !.sawEOF
}

func ( *body) ( func()) {
	.mu.Lock()
	defer .mu.Unlock()
	.onHitEOF = 
}
bodyLocked is a io.Reader reading from a *body when its mutex is already held.
type bodyLocked struct {
	b *body
}

func ( bodyLocked) ( []byte) ( int,  error) {
	if .b.closed {
		return 0, ErrBodyReadAfterClose
	}
	return .b.readLocked()
}
parseContentLength trims whitespace from s and returns -1 if no value is set, or the value if it's >= 0.
func ( string) (int64, error) {
	 = textproto.TrimString()
	if  == "" {
		return -1, nil
	}
	,  := strconv.ParseUint(, 10, 63)
	if  != nil {
		return 0, badStringError("bad Content-Length", )
	}
	return int64(), nil

}
finishAsyncByteRead finishes reading the 1-byte sniff from the ContentLength==0, Body!=nil case.
type finishAsyncByteRead struct {
	tw *transferWriter
}

func ( finishAsyncByteRead) ( []byte) ( int,  error) {
	if len() == 0 {
		return
	}
	 := <-.tw.ByteReadCh
	,  = .n, .err
	if  == 1 {
		[0] = .b
	}
	return
}

var nopCloserType = reflect.TypeOf(io.NopCloser(nil))
isKnownInMemoryReader reports whether r is a type known to not block on Read. Its caller uses this as an optional optimization to send fewer TCP packets.
func ( io.Reader) bool {
	switch .(type) {
	case *bytes.Reader, *bytes.Buffer, *strings.Reader:
		return true
	}
	if reflect.TypeOf() == nopCloserType {
		return (reflect.ValueOf().Field(0).Interface().(io.Reader))
	}
	if ,  := .(*readTrackingBody);  {
		return (.ReadCloser)
	}
	return false
}
bufioFlushWriter is an io.Writer wrapper that flushes all writes on its wrapped writer if it's a *bufio.Writer.
type bufioFlushWriter struct{ w io.Writer }

func ( bufioFlushWriter) ( []byte) ( int,  error) {
	,  = .w.Write()
	if ,  := .w.(*bufio.Writer);  > 0 &&  {
		 := .Flush()
		if  != nil &&  == nil {
			 = 
		}
	}
	return