// 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 newTransferWriter( any) ( *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.
func ( *transferWriter) () bool {
	// 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
	}
	if requestMethodUsuallyLacksBody(.Method) {
		// 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 <- 
		close(.ByteReadCh)
	}(.Body)
	 := time.NewTimer(200 * time.Millisecond)
	select {
	case  := <-.ByteReadCh:
		.Stop()
		if .n == 0 && .err == io.EOF {
			// 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}
		}
	case <-.C:
		// 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.
		.Body = io.MultiReader(finishAsyncByteRead{}, .Body)
		// 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 noResponseBodyExpected( 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 {
			slices.Sort()
			// 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 !.ResponseToHEAD && .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, )
	}

	if !.ResponseToHEAD && chunked(.TransferEncoding) {
		// 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) {
	 := getCopyBuf()
	defer putCopyBuf()

	,  = io.CopyBuffer(, , )
	if  != nil &&  != io.EOF {
		.bodyReadError = 
	}
	return
}

// unwrapBody 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 ,  := unwrapNopCloser(.Body);  {
		return 
	}
	if ,  := .Body.(*readTrackingBody);  {
		.didRead = true
		return .ReadCloser
	}
	return .Body
}

type transferReader struct {
	// Input
	Header        Header
	StatusCode    int
	RequestMethod string
	ProtoMajor    int
	ProtoMinor    int
	// Output
	Body          io.ReadCloser
	ContentLength int64
	Chunked       bool
	Close         bool
	Trailer       Header
}

func ( *transferReader) (,  int) bool {
	return .ProtoMajor >  || (.ProtoMajor ==  && .ProtoMinor >= )
}

// bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC 7230, section 3.3.
func bodyAllowedForStatus( 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"}
	excludedHeadersNoBody   = map[string]bool{"Content-Length": true, "Transfer-Encoding": true}
)

func suppressedHeaders( int) []string {
	switch {
	case  == 304:
		// RFC 7232 section 4.1
		return suppressedHeaders304
	case !bodyAllowedForStatus():
		return suppressedHeadersNoBody
	}
	return nil
}

// msg is *Request or *Response.
func readTransfer( any,  *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
		.ProtoMinor = .ProtoMinor
		// 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["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:
		if  == -1 && !.Chunked && bodyAllowedForStatus(.StatusCode) {
			// 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}
	default:
		// realLength < 0, i.e. "Content-Length" not mentioned in header
		if .Close {
			// Close semantics (i.e. HTTP/1.0)
			.Body = &body{src: , closing: .Close}
		} else {
			// 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 chunked( []string) bool { return len() > 0 && [0] == "chunked" }

// Checks whether the encoding is explicitly "identity".
func isIdentity( []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 isUnsupportedTEError( 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 !ascii.EqualFold([0], "chunked") {
		return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", [0])}
	}

	.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 fixLength( bool,  int,  string,  Header,  bool) ( int64,  error) {
	 := !
	 := ["Content-Length"]

	// Hardening against HTTP request smuggling
	if len() > 1 {
		// 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"]
	}

	// Reject requests with invalid Content-Length headers.
	if len() > 0 {
		,  = parseContentLength()
		if  != nil {
			return -1, 
		}
	}

	// Logic based on response type or status
	if  && noResponseBodyExpected() {
		return 0, nil
	}
	if /100 == 1 {
		return 0, nil
	}
	switch  {
	case 204, 304:
		return 0, nil
	}

	// According to RFC 9112, "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 11.2) or response splitting (Section 11.1)
	// and ought to be handled as an error. An intermediary that chooses to forward
	// the message MUST first remove the received Content-Length field and process
	// the Transfer-Encoding (as described below) prior to forwarding the message downstream."
	//
	// Chunked-encoding requests with either valid Content-Length
	// headers or no Content-Length headers are accepted after removing
	// the Content-Length field from header.
	//
	// Logic based on Transfer-Encoding
	if  {
		.Del("Content-Length")
		return -1, nil
	}

	// Logic based on Content-Length
	if len() > 0 {
		return , nil
	}

	.Del("Content-Length")

	if  {
		// 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 shouldClose(,  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 fixTrailer( Header,  bool) (Header, error) {
	,  := ["Trailer"]
	if ! {
		return nil, nil
	}
	if ! {
		// 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          any           // 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 {
		.sawEOF = true
		// 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
		} else {
			// 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 seeUpcomingDoubleCRLF( *bufio.Reader) bool {
	for  := 4; ; ++ {
		// 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")

func ( *body) () error {
	// 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 mergeSetHeader( *Header,  Header) {
	if * == nil {
		* = 
		return
	}
	maps.Copy(*, )
}

// 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 {
	case .sawEOF:
		// Already saw EOF, so no need going to look for it.
	case .hdr == nil && .closing:
		// no trailer and closing the connection next.
		// no point in reading to EOF.
	case .doEarlyClose:
		// Read up to maxPostHandlerReadBytes bytes of the body, looking
		// for EOF (and trailers), so we can re-use this connection.
		if ,  := .src.(*io.LimitedReader);  && .N > maxPostHandlerReadBytes {
			// There was a declared Content-Length, and we have more bytes remaining
			// than our maxPostHandlerReadBytes tolerance. So, give up.
			.earlyClose = true
		} else {
			var  int64
			// 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
			}
		}
	default:
		// 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 an 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()
}

var httplaxcontentlength = godebug.New("httplaxcontentlength")

// parseContentLength checks that the header is valid and then trims
// whitespace. It returns -1 if no value is set otherwise the value
// if it's >= 0.
func parseContentLength( []string) (int64, error) {
	if len() == 0 {
		return -1, nil
	}
	 := textproto.TrimString([0])

	// The Content-Length must be a valid numeric value.
	// See: https://datatracker.ietf.org/doc/html/rfc2616/#section-14.13
	if  == "" {
		if httplaxcontentlength.Value() == "1" {
			httplaxcontentlength.IncNonDefault()
			return -1, nil
		}
		return 0, badStringError("invalid empty Content-Length", )
	}
	,  := 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
	}
	if  == nil {
		 = io.EOF
	}
	return
}

var nopCloserType = reflect.TypeOf(io.NopCloser(nil))
var nopCloserWriterToType = reflect.TypeOf(io.NopCloser(struct {
	io.Reader
	io.WriterTo
}{}))

// unwrapNopCloser return the underlying reader and true if r is a NopCloser
// else it return false.
func unwrapNopCloser( io.Reader) ( io.Reader,  bool) {
	switch reflect.TypeOf() {
	case nopCloserType, nopCloserWriterToType:
		return reflect.ValueOf().Field(0).Interface().(io.Reader), true
	default:
		return nil, false
	}
}

// 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 isKnownInMemoryReader( io.Reader) bool {
	switch .(type) {
	case *bytes.Reader, *bytes.Buffer, *strings.Reader:
		return true
	}
	if ,  := unwrapNopCloser();  {
		return ()
	}
	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
}