Source file
    src/net/http/transfer.go
  
  
     1  
     2  
     3  
     4  
     5  package http
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"errors"
    11  	"fmt"
    12  	"internal/godebug"
    13  	"io"
    14  	"maps"
    15  	"net/http/httptrace"
    16  	"net/http/internal"
    17  	"net/http/internal/ascii"
    18  	"net/textproto"
    19  	"reflect"
    20  	"slices"
    21  	"strconv"
    22  	"strings"
    23  	"sync"
    24  	"time"
    25  
    26  	"golang.org/x/net/http/httpguts"
    27  )
    28  
    29  
    30  
    31  var ErrLineTooLong = internal.ErrLineTooLong
    32  
    33  type errorReader struct {
    34  	err error
    35  }
    36  
    37  func (r errorReader) Read(p []byte) (n int, err error) {
    38  	return 0, r.err
    39  }
    40  
    41  type byteReader struct {
    42  	b    byte
    43  	done bool
    44  }
    45  
    46  func (br *byteReader) Read(p []byte) (n int, err error) {
    47  	if br.done {
    48  		return 0, io.EOF
    49  	}
    50  	if len(p) == 0 {
    51  		return 0, nil
    52  	}
    53  	br.done = true
    54  	p[0] = br.b
    55  	return 1, io.EOF
    56  }
    57  
    58  
    59  
    60  
    61  type transferWriter struct {
    62  	Method           string
    63  	Body             io.Reader
    64  	BodyCloser       io.Closer
    65  	ResponseToHEAD   bool
    66  	ContentLength    int64 
    67  	Close            bool
    68  	TransferEncoding []string
    69  	Header           Header
    70  	Trailer          Header
    71  	IsResponse       bool
    72  	bodyReadError    error 
    73  
    74  	FlushHeaders bool            
    75  	ByteReadCh   chan readResult 
    76  }
    77  
    78  func newTransferWriter(r any) (t *transferWriter, err error) {
    79  	t = &transferWriter{}
    80  
    81  	
    82  	atLeastHTTP11 := false
    83  	switch rr := r.(type) {
    84  	case *Request:
    85  		if rr.ContentLength != 0 && rr.Body == nil {
    86  			return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
    87  		}
    88  		t.Method = valueOrDefault(rr.Method, "GET")
    89  		t.Close = rr.Close
    90  		t.TransferEncoding = rr.TransferEncoding
    91  		t.Header = rr.Header
    92  		t.Trailer = rr.Trailer
    93  		t.Body = rr.Body
    94  		t.BodyCloser = rr.Body
    95  		t.ContentLength = rr.outgoingLength()
    96  		if t.ContentLength < 0 && len(t.TransferEncoding) == 0 && t.shouldSendChunkedRequestBody() {
    97  			t.TransferEncoding = []string{"chunked"}
    98  		}
    99  		
   100  		
   101  		
   102  		
   103  		
   104  		
   105  		
   106  		if t.ContentLength != 0 && !isKnownInMemoryReader(t.Body) {
   107  			t.FlushHeaders = true
   108  		}
   109  
   110  		atLeastHTTP11 = true 
   111  	case *Response:
   112  		t.IsResponse = true
   113  		if rr.Request != nil {
   114  			t.Method = rr.Request.Method
   115  		}
   116  		t.Body = rr.Body
   117  		t.BodyCloser = rr.Body
   118  		t.ContentLength = rr.ContentLength
   119  		t.Close = rr.Close
   120  		t.TransferEncoding = rr.TransferEncoding
   121  		t.Header = rr.Header
   122  		t.Trailer = rr.Trailer
   123  		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
   124  		t.ResponseToHEAD = noResponseBodyExpected(t.Method)
   125  	}
   126  
   127  	
   128  	if t.ResponseToHEAD {
   129  		t.Body = nil
   130  		if chunked(t.TransferEncoding) {
   131  			t.ContentLength = -1
   132  		}
   133  	} else {
   134  		if !atLeastHTTP11 || t.Body == nil {
   135  			t.TransferEncoding = nil
   136  		}
   137  		if chunked(t.TransferEncoding) {
   138  			t.ContentLength = -1
   139  		} else if t.Body == nil { 
   140  			t.ContentLength = 0
   141  		}
   142  	}
   143  
   144  	
   145  	if !chunked(t.TransferEncoding) {
   146  		t.Trailer = nil
   147  	}
   148  
   149  	return t, nil
   150  }
   151  
   152  
   153  
   154  
   155  
   156  
   157  
   158  
   159  
   160  
   161  
   162  
   163  
   164  
   165  
   166  
   167  
   168  
   169  
   170  func (t *transferWriter) shouldSendChunkedRequestBody() bool {
   171  	
   172  	
   173  	if t.ContentLength >= 0 || t.Body == nil { 
   174  		return false
   175  	}
   176  	if t.Method == "CONNECT" {
   177  		return false
   178  	}
   179  	if requestMethodUsuallyLacksBody(t.Method) {
   180  		
   181  		
   182  		
   183  		t.probeRequestBody() 
   184  		return t.Body != nil
   185  	}
   186  	
   187  	
   188  	
   189  	
   190  	return true
   191  }
   192  
   193  
   194  
   195  
   196  
   197  
   198  
   199  
   200  
   201  
   202  
   203  
   204  
   205  
   206  
   207  
   208  func (t *transferWriter) probeRequestBody() {
   209  	t.ByteReadCh = make(chan readResult, 1)
   210  	go func(body io.Reader) {
   211  		var buf [1]byte
   212  		var rres readResult
   213  		rres.n, rres.err = body.Read(buf[:])
   214  		if rres.n == 1 {
   215  			rres.b = buf[0]
   216  		}
   217  		t.ByteReadCh <- rres
   218  		close(t.ByteReadCh)
   219  	}(t.Body)
   220  	timer := time.NewTimer(200 * time.Millisecond)
   221  	select {
   222  	case rres := <-t.ByteReadCh:
   223  		timer.Stop()
   224  		if rres.n == 0 && rres.err == io.EOF {
   225  			
   226  			t.Body = nil
   227  			t.ContentLength = 0
   228  		} else if rres.n == 1 {
   229  			if rres.err != nil {
   230  				t.Body = io.MultiReader(&byteReader{b: rres.b}, errorReader{rres.err})
   231  			} else {
   232  				t.Body = io.MultiReader(&byteReader{b: rres.b}, t.Body)
   233  			}
   234  		} else if rres.err != nil {
   235  			t.Body = errorReader{rres.err}
   236  		}
   237  	case <-timer.C:
   238  		
   239  		
   240  		
   241  		
   242  		t.Body = io.MultiReader(finishAsyncByteRead{t}, t.Body)
   243  		
   244  		
   245  		
   246  		t.FlushHeaders = true
   247  	}
   248  }
   249  
   250  func noResponseBodyExpected(requestMethod string) bool {
   251  	return requestMethod == "HEAD"
   252  }
   253  
   254  func (t *transferWriter) shouldSendContentLength() bool {
   255  	if chunked(t.TransferEncoding) {
   256  		return false
   257  	}
   258  	if t.ContentLength > 0 {
   259  		return true
   260  	}
   261  	if t.ContentLength < 0 {
   262  		return false
   263  	}
   264  	
   265  	if t.Method == "POST" || t.Method == "PUT" || t.Method == "PATCH" {
   266  		return true
   267  	}
   268  	if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
   269  		if t.Method == "GET" || t.Method == "HEAD" {
   270  			return false
   271  		}
   272  		return true
   273  	}
   274  
   275  	return false
   276  }
   277  
   278  func (t *transferWriter) writeHeader(w io.Writer, trace *httptrace.ClientTrace) error {
   279  	if t.Close && !hasToken(t.Header.get("Connection"), "close") {
   280  		if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
   281  			return err
   282  		}
   283  		if trace != nil && trace.WroteHeaderField != nil {
   284  			trace.WroteHeaderField("Connection", []string{"close"})
   285  		}
   286  	}
   287  
   288  	
   289  	
   290  	
   291  	if t.shouldSendContentLength() {
   292  		if _, err := io.WriteString(w, "Content-Length: "); err != nil {
   293  			return err
   294  		}
   295  		if _, err := io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n"); err != nil {
   296  			return err
   297  		}
   298  		if trace != nil && trace.WroteHeaderField != nil {
   299  			trace.WroteHeaderField("Content-Length", []string{strconv.FormatInt(t.ContentLength, 10)})
   300  		}
   301  	} else if chunked(t.TransferEncoding) {
   302  		if _, err := io.WriteString(w, "Transfer-Encoding: chunked\r\n"); err != nil {
   303  			return err
   304  		}
   305  		if trace != nil && trace.WroteHeaderField != nil {
   306  			trace.WroteHeaderField("Transfer-Encoding", []string{"chunked"})
   307  		}
   308  	}
   309  
   310  	
   311  	if t.Trailer != nil {
   312  		keys := make([]string, 0, len(t.Trailer))
   313  		for k := range t.Trailer {
   314  			k = CanonicalHeaderKey(k)
   315  			switch k {
   316  			case "Transfer-Encoding", "Trailer", "Content-Length":
   317  				return badStringError("invalid Trailer key", k)
   318  			}
   319  			keys = append(keys, k)
   320  		}
   321  		if len(keys) > 0 {
   322  			slices.Sort(keys)
   323  			
   324  			
   325  			if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
   326  				return err
   327  			}
   328  			if trace != nil && trace.WroteHeaderField != nil {
   329  				trace.WroteHeaderField("Trailer", keys)
   330  			}
   331  		}
   332  	}
   333  
   334  	return nil
   335  }
   336  
   337  
   338  func (t *transferWriter) writeBody(w io.Writer) (err error) {
   339  	var ncopy int64
   340  	closed := false
   341  	defer func() {
   342  		if closed || t.BodyCloser == nil {
   343  			return
   344  		}
   345  		if closeErr := t.BodyCloser.Close(); closeErr != nil && err == nil {
   346  			err = closeErr
   347  		}
   348  	}()
   349  
   350  	
   351  	
   352  	
   353  	
   354  	if !t.ResponseToHEAD && t.Body != nil {
   355  		var body = t.unwrapBody()
   356  		if chunked(t.TransferEncoding) {
   357  			if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
   358  				w = &internal.FlushAfterChunkWriter{Writer: bw}
   359  			}
   360  			cw := internal.NewChunkedWriter(w)
   361  			_, err = t.doBodyCopy(cw, body)
   362  			if err == nil {
   363  				err = cw.Close()
   364  			}
   365  		} else if t.ContentLength == -1 {
   366  			dst := w
   367  			if t.Method == "CONNECT" {
   368  				dst = bufioFlushWriter{dst}
   369  			}
   370  			ncopy, err = t.doBodyCopy(dst, body)
   371  		} else {
   372  			ncopy, err = t.doBodyCopy(w, io.LimitReader(body, t.ContentLength))
   373  			if err != nil {
   374  				return err
   375  			}
   376  			var nextra int64
   377  			nextra, err = t.doBodyCopy(io.Discard, body)
   378  			ncopy += nextra
   379  		}
   380  		if err != nil {
   381  			return err
   382  		}
   383  	}
   384  	if t.BodyCloser != nil {
   385  		closed = true
   386  		if err := t.BodyCloser.Close(); err != nil {
   387  			return err
   388  		}
   389  	}
   390  
   391  	if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
   392  		return fmt.Errorf("http: ContentLength=%d with Body length %d",
   393  			t.ContentLength, ncopy)
   394  	}
   395  
   396  	if !t.ResponseToHEAD && chunked(t.TransferEncoding) {
   397  		
   398  		if t.Trailer != nil {
   399  			if err := t.Trailer.Write(w); err != nil {
   400  				return err
   401  			}
   402  		}
   403  		
   404  		_, err = io.WriteString(w, "\r\n")
   405  	}
   406  	return err
   407  }
   408  
   409  
   410  
   411  
   412  
   413  func (t *transferWriter) doBodyCopy(dst io.Writer, src io.Reader) (n int64, err error) {
   414  	buf := getCopyBuf()
   415  	defer putCopyBuf(buf)
   416  
   417  	n, err = io.CopyBuffer(dst, src, buf)
   418  	if err != nil && err != io.EOF {
   419  		t.bodyReadError = err
   420  	}
   421  	return
   422  }
   423  
   424  
   425  
   426  
   427  
   428  
   429  func (t *transferWriter) unwrapBody() io.Reader {
   430  	if r, ok := unwrapNopCloser(t.Body); ok {
   431  		return r
   432  	}
   433  	if r, ok := t.Body.(*readTrackingBody); ok {
   434  		r.didRead = true
   435  		return r.ReadCloser
   436  	}
   437  	return t.Body
   438  }
   439  
   440  type transferReader struct {
   441  	
   442  	Header        Header
   443  	StatusCode    int
   444  	RequestMethod string
   445  	ProtoMajor    int
   446  	ProtoMinor    int
   447  	
   448  	Body          io.ReadCloser
   449  	ContentLength int64
   450  	Chunked       bool
   451  	Close         bool
   452  	Trailer       Header
   453  }
   454  
   455  func (t *transferReader) protoAtLeast(m, n int) bool {
   456  	return t.ProtoMajor > m || (t.ProtoMajor == m && t.ProtoMinor >= n)
   457  }
   458  
   459  
   460  
   461  func bodyAllowedForStatus(status int) bool {
   462  	switch {
   463  	case status >= 100 && status <= 199:
   464  		return false
   465  	case status == 204:
   466  		return false
   467  	case status == 304:
   468  		return false
   469  	}
   470  	return true
   471  }
   472  
   473  var (
   474  	suppressedHeaders304    = []string{"Content-Type", "Content-Length", "Transfer-Encoding"}
   475  	suppressedHeadersNoBody = []string{"Content-Length", "Transfer-Encoding"}
   476  	excludedHeadersNoBody   = map[string]bool{"Content-Length": true, "Transfer-Encoding": true}
   477  )
   478  
   479  func suppressedHeaders(status int) []string {
   480  	switch {
   481  	case status == 304:
   482  		
   483  		return suppressedHeaders304
   484  	case !bodyAllowedForStatus(status):
   485  		return suppressedHeadersNoBody
   486  	}
   487  	return nil
   488  }
   489  
   490  
   491  func readTransfer(msg any, r *bufio.Reader) (err error) {
   492  	t := &transferReader{RequestMethod: "GET"}
   493  
   494  	
   495  	isResponse := false
   496  	switch rr := msg.(type) {
   497  	case *Response:
   498  		t.Header = rr.Header
   499  		t.StatusCode = rr.StatusCode
   500  		t.ProtoMajor = rr.ProtoMajor
   501  		t.ProtoMinor = rr.ProtoMinor
   502  		t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header, true)
   503  		isResponse = true
   504  		if rr.Request != nil {
   505  			t.RequestMethod = rr.Request.Method
   506  		}
   507  	case *Request:
   508  		t.Header = rr.Header
   509  		t.RequestMethod = rr.Method
   510  		t.ProtoMajor = rr.ProtoMajor
   511  		t.ProtoMinor = rr.ProtoMinor
   512  		
   513  		
   514  		t.StatusCode = 200
   515  		t.Close = rr.Close
   516  	default:
   517  		panic("unexpected type")
   518  	}
   519  
   520  	
   521  	if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
   522  		t.ProtoMajor, t.ProtoMinor = 1, 1
   523  	}
   524  
   525  	
   526  	if err := t.parseTransferEncoding(); err != nil {
   527  		return err
   528  	}
   529  
   530  	realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.Chunked)
   531  	if err != nil {
   532  		return err
   533  	}
   534  	if isResponse && t.RequestMethod == "HEAD" {
   535  		if n, err := parseContentLength(t.Header["Content-Length"]); err != nil {
   536  			return err
   537  		} else {
   538  			t.ContentLength = n
   539  		}
   540  	} else {
   541  		t.ContentLength = realLength
   542  	}
   543  
   544  	
   545  	t.Trailer, err = fixTrailer(t.Header, t.Chunked)
   546  	if err != nil {
   547  		return err
   548  	}
   549  
   550  	
   551  	
   552  	
   553  	switch msg.(type) {
   554  	case *Response:
   555  		if realLength == -1 && !t.Chunked && bodyAllowedForStatus(t.StatusCode) {
   556  			
   557  			t.Close = true
   558  		}
   559  	}
   560  
   561  	
   562  	
   563  	switch {
   564  	case t.Chunked:
   565  		if isResponse && (noResponseBodyExpected(t.RequestMethod) || !bodyAllowedForStatus(t.StatusCode)) {
   566  			t.Body = NoBody
   567  		} else {
   568  			t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
   569  		}
   570  	case realLength == 0:
   571  		t.Body = NoBody
   572  	case realLength > 0:
   573  		t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
   574  	default:
   575  		
   576  		if t.Close {
   577  			
   578  			t.Body = &body{src: r, closing: t.Close}
   579  		} else {
   580  			
   581  			t.Body = NoBody
   582  		}
   583  	}
   584  
   585  	
   586  	switch rr := msg.(type) {
   587  	case *Request:
   588  		rr.Body = t.Body
   589  		rr.ContentLength = t.ContentLength
   590  		if t.Chunked {
   591  			rr.TransferEncoding = []string{"chunked"}
   592  		}
   593  		rr.Close = t.Close
   594  		rr.Trailer = t.Trailer
   595  	case *Response:
   596  		rr.Body = t.Body
   597  		rr.ContentLength = t.ContentLength
   598  		if t.Chunked {
   599  			rr.TransferEncoding = []string{"chunked"}
   600  		}
   601  		rr.Close = t.Close
   602  		rr.Trailer = t.Trailer
   603  	}
   604  
   605  	return nil
   606  }
   607  
   608  
   609  func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
   610  
   611  
   612  func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
   613  
   614  
   615  type unsupportedTEError struct {
   616  	err string
   617  }
   618  
   619  func (uste *unsupportedTEError) Error() string {
   620  	return uste.err
   621  }
   622  
   623  
   624  
   625  func isUnsupportedTEError(err error) bool {
   626  	_, ok := err.(*unsupportedTEError)
   627  	return ok
   628  }
   629  
   630  
   631  func (t *transferReader) parseTransferEncoding() error {
   632  	raw, present := t.Header["Transfer-Encoding"]
   633  	if !present {
   634  		return nil
   635  	}
   636  	delete(t.Header, "Transfer-Encoding")
   637  
   638  	
   639  	if !t.protoAtLeast(1, 1) {
   640  		return nil
   641  	}
   642  
   643  	
   644  	
   645  	
   646  	
   647  	if len(raw) != 1 {
   648  		return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", raw)}
   649  	}
   650  	if !ascii.EqualFold(raw[0], "chunked") {
   651  		return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", raw[0])}
   652  	}
   653  
   654  	t.Chunked = true
   655  	return nil
   656  }
   657  
   658  
   659  
   660  
   661  func fixLength(isResponse bool, status int, requestMethod string, header Header, chunked bool) (n int64, err error) {
   662  	isRequest := !isResponse
   663  	contentLens := header["Content-Length"]
   664  
   665  	
   666  	if len(contentLens) > 1 {
   667  		
   668  		
   669  		
   670  		
   671  		first := textproto.TrimString(contentLens[0])
   672  		for _, ct := range contentLens[1:] {
   673  			if first != textproto.TrimString(ct) {
   674  				return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", contentLens)
   675  			}
   676  		}
   677  
   678  		
   679  		header.Del("Content-Length")
   680  		header.Add("Content-Length", first)
   681  
   682  		contentLens = header["Content-Length"]
   683  	}
   684  
   685  	
   686  	if len(contentLens) > 0 {
   687  		n, err = parseContentLength(contentLens)
   688  		if err != nil {
   689  			return -1, err
   690  		}
   691  	}
   692  
   693  	
   694  	if isResponse && noResponseBodyExpected(requestMethod) {
   695  		return 0, nil
   696  	}
   697  	if status/100 == 1 {
   698  		return 0, nil
   699  	}
   700  	switch status {
   701  	case 204, 304:
   702  		return 0, nil
   703  	}
   704  
   705  	
   706  	
   707  	
   708  	
   709  	
   710  	
   711  	
   712  	
   713  	
   714  	
   715  	
   716  	
   717  	
   718  	if chunked {
   719  		header.Del("Content-Length")
   720  		return -1, nil
   721  	}
   722  
   723  	
   724  	if len(contentLens) > 0 {
   725  		return n, nil
   726  	}
   727  
   728  	header.Del("Content-Length")
   729  
   730  	if isRequest {
   731  		
   732  		
   733  		
   734  		
   735  		
   736  		
   737  		
   738  		return 0, nil
   739  	}
   740  
   741  	
   742  	return -1, nil
   743  }
   744  
   745  
   746  
   747  
   748  func shouldClose(major, minor int, header Header, removeCloseHeader bool) bool {
   749  	if major < 1 {
   750  		return true
   751  	}
   752  
   753  	conv := header["Connection"]
   754  	hasClose := httpguts.HeaderValuesContainsToken(conv, "close")
   755  	if major == 1 && minor == 0 {
   756  		return hasClose || !httpguts.HeaderValuesContainsToken(conv, "keep-alive")
   757  	}
   758  
   759  	if hasClose && removeCloseHeader {
   760  		header.Del("Connection")
   761  	}
   762  
   763  	return hasClose
   764  }
   765  
   766  
   767  func fixTrailer(header Header, chunked bool) (Header, error) {
   768  	vv, ok := header["Trailer"]
   769  	if !ok {
   770  		return nil, nil
   771  	}
   772  	if !chunked {
   773  		
   774  		
   775  		
   776  		
   777  		
   778  		
   779  		
   780  		return nil, nil
   781  	}
   782  	header.Del("Trailer")
   783  
   784  	trailer := make(Header)
   785  	var err error
   786  	for _, v := range vv {
   787  		foreachHeaderElement(v, func(key string) {
   788  			key = CanonicalHeaderKey(key)
   789  			switch key {
   790  			case "Transfer-Encoding", "Trailer", "Content-Length":
   791  				if err == nil {
   792  					err = badStringError("bad trailer key", key)
   793  					return
   794  				}
   795  			}
   796  			trailer[key] = nil
   797  		})
   798  	}
   799  	if err != nil {
   800  		return nil, err
   801  	}
   802  	if len(trailer) == 0 {
   803  		return nil, nil
   804  	}
   805  	return trailer, nil
   806  }
   807  
   808  
   809  
   810  
   811  type body struct {
   812  	src          io.Reader
   813  	hdr          any           
   814  	r            *bufio.Reader 
   815  	closing      bool          
   816  	doEarlyClose bool          
   817  
   818  	mu         sync.Mutex 
   819  	sawEOF     bool
   820  	closed     bool
   821  	earlyClose bool   
   822  	onHitEOF   func() 
   823  }
   824  
   825  
   826  
   827  
   828  
   829  var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
   830  
   831  func (b *body) Read(p []byte) (n int, err error) {
   832  	b.mu.Lock()
   833  	defer b.mu.Unlock()
   834  	if b.closed {
   835  		return 0, ErrBodyReadAfterClose
   836  	}
   837  	return b.readLocked(p)
   838  }
   839  
   840  
   841  func (b *body) readLocked(p []byte) (n int, err error) {
   842  	if b.sawEOF {
   843  		return 0, io.EOF
   844  	}
   845  	n, err = b.src.Read(p)
   846  
   847  	if err == io.EOF {
   848  		b.sawEOF = true
   849  		
   850  		if b.hdr != nil {
   851  			if e := b.readTrailer(); e != nil {
   852  				err = e
   853  				
   854  				
   855  				
   856  				
   857  				b.sawEOF = false
   858  				b.closed = true
   859  			}
   860  			b.hdr = nil
   861  		} else {
   862  			
   863  			
   864  			if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > 0 {
   865  				err = io.ErrUnexpectedEOF
   866  			}
   867  		}
   868  	}
   869  
   870  	
   871  	
   872  	
   873  	
   874  	
   875  	if err == nil && n > 0 {
   876  		if lr, ok := b.src.(*io.LimitedReader); ok && lr.N == 0 {
   877  			err = io.EOF
   878  			b.sawEOF = true
   879  		}
   880  	}
   881  
   882  	if b.sawEOF && b.onHitEOF != nil {
   883  		b.onHitEOF()
   884  	}
   885  
   886  	return n, err
   887  }
   888  
   889  var (
   890  	singleCRLF = []byte("\r\n")
   891  	doubleCRLF = []byte("\r\n\r\n")
   892  )
   893  
   894  func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
   895  	for peekSize := 4; ; peekSize++ {
   896  		
   897  		
   898  		buf, err := r.Peek(peekSize)
   899  		if bytes.HasSuffix(buf, doubleCRLF) {
   900  			return true
   901  		}
   902  		if err != nil {
   903  			break
   904  		}
   905  	}
   906  	return false
   907  }
   908  
   909  var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
   910  
   911  func (b *body) readTrailer() error {
   912  	
   913  	buf, err := b.r.Peek(2)
   914  	if bytes.Equal(buf, singleCRLF) {
   915  		b.r.Discard(2)
   916  		return nil
   917  	}
   918  	if len(buf) < 2 {
   919  		return errTrailerEOF
   920  	}
   921  	if err != nil {
   922  		return err
   923  	}
   924  
   925  	
   926  	
   927  	
   928  	
   929  	
   930  	
   931  	
   932  	
   933  	if !seeUpcomingDoubleCRLF(b.r) {
   934  		return errors.New("http: suspiciously long trailer after chunked body")
   935  	}
   936  
   937  	hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
   938  	if err != nil {
   939  		if err == io.EOF {
   940  			return errTrailerEOF
   941  		}
   942  		return err
   943  	}
   944  	switch rr := b.hdr.(type) {
   945  	case *Request:
   946  		mergeSetHeader(&rr.Trailer, Header(hdr))
   947  	case *Response:
   948  		mergeSetHeader(&rr.Trailer, Header(hdr))
   949  	}
   950  	return nil
   951  }
   952  
   953  func mergeSetHeader(dst *Header, src Header) {
   954  	if *dst == nil {
   955  		*dst = src
   956  		return
   957  	}
   958  	maps.Copy(*dst, src)
   959  }
   960  
   961  
   962  
   963  
   964  func (b *body) unreadDataSizeLocked() int64 {
   965  	if lr, ok := b.src.(*io.LimitedReader); ok {
   966  		return lr.N
   967  	}
   968  	return -1
   969  }
   970  
   971  func (b *body) Close() error {
   972  	b.mu.Lock()
   973  	defer b.mu.Unlock()
   974  	if b.closed {
   975  		return nil
   976  	}
   977  	var err error
   978  	switch {
   979  	case b.sawEOF:
   980  		
   981  	case b.hdr == nil && b.closing:
   982  		
   983  		
   984  	case b.doEarlyClose:
   985  		
   986  		
   987  		if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > maxPostHandlerReadBytes {
   988  			
   989  			
   990  			b.earlyClose = true
   991  		} else {
   992  			var n int64
   993  			
   994  			
   995  			n, err = io.CopyN(io.Discard, bodyLocked{b}, maxPostHandlerReadBytes)
   996  			if err == io.EOF {
   997  				err = nil
   998  			}
   999  			if n == maxPostHandlerReadBytes {
  1000  				b.earlyClose = true
  1001  			}
  1002  		}
  1003  	default:
  1004  		
  1005  		
  1006  		_, err = io.Copy(io.Discard, bodyLocked{b})
  1007  	}
  1008  	b.closed = true
  1009  	return err
  1010  }
  1011  
  1012  func (b *body) didEarlyClose() bool {
  1013  	b.mu.Lock()
  1014  	defer b.mu.Unlock()
  1015  	return b.earlyClose
  1016  }
  1017  
  1018  
  1019  
  1020  func (b *body) bodyRemains() bool {
  1021  	b.mu.Lock()
  1022  	defer b.mu.Unlock()
  1023  	return !b.sawEOF
  1024  }
  1025  
  1026  func (b *body) registerOnHitEOF(fn func()) {
  1027  	b.mu.Lock()
  1028  	defer b.mu.Unlock()
  1029  	b.onHitEOF = fn
  1030  }
  1031  
  1032  
  1033  
  1034  type bodyLocked struct {
  1035  	b *body
  1036  }
  1037  
  1038  func (bl bodyLocked) Read(p []byte) (n int, err error) {
  1039  	if bl.b.closed {
  1040  		return 0, ErrBodyReadAfterClose
  1041  	}
  1042  	return bl.b.readLocked(p)
  1043  }
  1044  
  1045  var httplaxcontentlength = godebug.New("httplaxcontentlength")
  1046  
  1047  
  1048  
  1049  
  1050  func parseContentLength(clHeaders []string) (int64, error) {
  1051  	if len(clHeaders) == 0 {
  1052  		return -1, nil
  1053  	}
  1054  	cl := textproto.TrimString(clHeaders[0])
  1055  
  1056  	
  1057  	
  1058  	if cl == "" {
  1059  		if httplaxcontentlength.Value() == "1" {
  1060  			httplaxcontentlength.IncNonDefault()
  1061  			return -1, nil
  1062  		}
  1063  		return 0, badStringError("invalid empty Content-Length", cl)
  1064  	}
  1065  	n, err := strconv.ParseUint(cl, 10, 63)
  1066  	if err != nil {
  1067  		return 0, badStringError("bad Content-Length", cl)
  1068  	}
  1069  	return int64(n), nil
  1070  }
  1071  
  1072  
  1073  
  1074  type finishAsyncByteRead struct {
  1075  	tw *transferWriter
  1076  }
  1077  
  1078  func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) {
  1079  	if len(p) == 0 {
  1080  		return
  1081  	}
  1082  	rres := <-fr.tw.ByteReadCh
  1083  	n, err = rres.n, rres.err
  1084  	if n == 1 {
  1085  		p[0] = rres.b
  1086  	}
  1087  	if err == nil {
  1088  		err = io.EOF
  1089  	}
  1090  	return
  1091  }
  1092  
  1093  var nopCloserType = reflect.TypeOf(io.NopCloser(nil))
  1094  var nopCloserWriterToType = reflect.TypeOf(io.NopCloser(struct {
  1095  	io.Reader
  1096  	io.WriterTo
  1097  }{}))
  1098  
  1099  
  1100  
  1101  func unwrapNopCloser(r io.Reader) (underlyingReader io.Reader, isNopCloser bool) {
  1102  	switch reflect.TypeOf(r) {
  1103  	case nopCloserType, nopCloserWriterToType:
  1104  		return reflect.ValueOf(r).Field(0).Interface().(io.Reader), true
  1105  	default:
  1106  		return nil, false
  1107  	}
  1108  }
  1109  
  1110  
  1111  
  1112  
  1113  func isKnownInMemoryReader(r io.Reader) bool {
  1114  	switch r.(type) {
  1115  	case *bytes.Reader, *bytes.Buffer, *strings.Reader:
  1116  		return true
  1117  	}
  1118  	if r, ok := unwrapNopCloser(r); ok {
  1119  		return isKnownInMemoryReader(r)
  1120  	}
  1121  	if r, ok := r.(*readTrackingBody); ok {
  1122  		return isKnownInMemoryReader(r.ReadCloser)
  1123  	}
  1124  	return false
  1125  }
  1126  
  1127  
  1128  
  1129  type bufioFlushWriter struct{ w io.Writer }
  1130  
  1131  func (fw bufioFlushWriter) Write(p []byte) (n int, err error) {
  1132  	n, err = fw.w.Write(p)
  1133  	if bw, ok := fw.w.(*bufio.Writer); n > 0 && ok {
  1134  		ferr := bw.Flush()
  1135  		if ferr != nil && err == nil {
  1136  			err = ferr
  1137  		}
  1138  	}
  1139  	return
  1140  }
  1141  
View as plain text