github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/net/http/transfer.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package http
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"errors"
    11  	"fmt"
    12  	"io"
    13  	"io/ioutil"
    14  	"net/http/internal"
    15  	"net/textproto"
    16  	"sort"
    17  	"strconv"
    18  	"strings"
    19  	"sync"
    20  
    21  	"golang_org/x/net/lex/httplex"
    22  )
    23  
    24  // ErrLineTooLong is returned when reading request or response bodies
    25  // with malformed chunked encoding.
    26  var ErrLineTooLong = internal.ErrLineTooLong
    27  
    28  type errorReader struct {
    29  	err error
    30  }
    31  
    32  func (r errorReader) Read(p []byte) (n int, err error) {
    33  	return 0, r.err
    34  }
    35  
    36  // transferWriter inspects the fields of a user-supplied Request or Response,
    37  // sanitizes them without changing the user object and provides methods for
    38  // writing the respective header, body and trailer in wire format.
    39  type transferWriter struct {
    40  	Method           string
    41  	Body             io.Reader
    42  	BodyCloser       io.Closer
    43  	ResponseToHEAD   bool
    44  	ContentLength    int64 // -1 means unknown, 0 means exactly none
    45  	Close            bool
    46  	TransferEncoding []string
    47  	Trailer          Header
    48  	IsResponse       bool
    49  }
    50  
    51  func newTransferWriter(r interface{}) (t *transferWriter, err error) {
    52  	t = &transferWriter{}
    53  
    54  	// Extract relevant fields
    55  	atLeastHTTP11 := false
    56  	switch rr := r.(type) {
    57  	case *Request:
    58  		if rr.ContentLength != 0 && rr.Body == nil {
    59  			return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
    60  		}
    61  		t.Method = valueOrDefault(rr.Method, "GET")
    62  		t.Close = rr.Close
    63  		t.TransferEncoding = rr.TransferEncoding
    64  		t.Trailer = rr.Trailer
    65  		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
    66  
    67  		t.Body = rr.Body
    68  		t.ContentLength = rr.outgoingLength()
    69  		if t.Body != nil {
    70  			t.BodyCloser = rr.Body
    71  		}
    72  		if t.ContentLength < 0 && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
    73  			t.TransferEncoding = []string{"chunked"}
    74  		}
    75  	case *Response:
    76  		t.IsResponse = true
    77  		if rr.Request != nil {
    78  			t.Method = rr.Request.Method
    79  		}
    80  		t.Body = rr.Body
    81  		t.BodyCloser = rr.Body
    82  		t.ContentLength = rr.ContentLength
    83  		t.Close = rr.Close
    84  		t.TransferEncoding = rr.TransferEncoding
    85  		t.Trailer = rr.Trailer
    86  		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
    87  		t.ResponseToHEAD = noBodyExpected(t.Method)
    88  	}
    89  
    90  	// Sanitize Body,ContentLength,TransferEncoding
    91  	if t.ResponseToHEAD {
    92  		t.Body = nil
    93  		if chunked(t.TransferEncoding) {
    94  			t.ContentLength = -1
    95  		}
    96  	} else {
    97  		if !atLeastHTTP11 || t.Body == nil {
    98  			t.TransferEncoding = nil
    99  		}
   100  		if chunked(t.TransferEncoding) {
   101  			t.ContentLength = -1
   102  		} else if t.Body == nil { // no chunking, no body
   103  			t.ContentLength = 0
   104  		}
   105  	}
   106  
   107  	// Sanitize Trailer
   108  	if !chunked(t.TransferEncoding) {
   109  		t.Trailer = nil
   110  	}
   111  
   112  	return t, nil
   113  }
   114  
   115  func noBodyExpected(requestMethod string) bool {
   116  	return requestMethod == "HEAD"
   117  }
   118  
   119  func (t *transferWriter) shouldSendContentLength() bool {
   120  	if chunked(t.TransferEncoding) {
   121  		return false
   122  	}
   123  	if t.ContentLength > 0 {
   124  		return true
   125  	}
   126  	if t.ContentLength < 0 {
   127  		return false
   128  	}
   129  	// Many servers expect a Content-Length for these methods
   130  	if t.Method == "POST" || t.Method == "PUT" {
   131  		return true
   132  	}
   133  	if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
   134  		if t.Method == "GET" || t.Method == "HEAD" {
   135  			return false
   136  		}
   137  		return true
   138  	}
   139  
   140  	return false
   141  }
   142  
   143  func (t *transferWriter) WriteHeader(w io.Writer) error {
   144  	if t.Close {
   145  		if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
   146  			return err
   147  		}
   148  	}
   149  
   150  	// Write Content-Length and/or Transfer-Encoding whose values are a
   151  	// function of the sanitized field triple (Body, ContentLength,
   152  	// TransferEncoding)
   153  	if t.shouldSendContentLength() {
   154  		if _, err := io.WriteString(w, "Content-Length: "); err != nil {
   155  			return err
   156  		}
   157  		if _, err := io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n"); err != nil {
   158  			return err
   159  		}
   160  	} else if chunked(t.TransferEncoding) {
   161  		if _, err := io.WriteString(w, "Transfer-Encoding: chunked\r\n"); err != nil {
   162  			return err
   163  		}
   164  	}
   165  
   166  	// Write Trailer header
   167  	if t.Trailer != nil {
   168  		keys := make([]string, 0, len(t.Trailer))
   169  		for k := range t.Trailer {
   170  			k = CanonicalHeaderKey(k)
   171  			switch k {
   172  			case "Transfer-Encoding", "Trailer", "Content-Length":
   173  				return &badStringError{"invalid Trailer key", k}
   174  			}
   175  			keys = append(keys, k)
   176  		}
   177  		if len(keys) > 0 {
   178  			sort.Strings(keys)
   179  			// TODO: could do better allocation-wise here, but trailers are rare,
   180  			// so being lazy for now.
   181  			if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
   182  				return err
   183  			}
   184  		}
   185  	}
   186  
   187  	return nil
   188  }
   189  
   190  func (t *transferWriter) WriteBody(w io.Writer) error {
   191  	var err error
   192  	var ncopy int64
   193  
   194  	// Write body
   195  	if t.Body != nil {
   196  		if chunked(t.TransferEncoding) {
   197  			if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
   198  				w = &internal.FlushAfterChunkWriter{Writer: bw}
   199  			}
   200  			cw := internal.NewChunkedWriter(w)
   201  			_, err = io.Copy(cw, t.Body)
   202  			if err == nil {
   203  				err = cw.Close()
   204  			}
   205  		} else if t.ContentLength == -1 {
   206  			ncopy, err = io.Copy(w, t.Body)
   207  		} else {
   208  			ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
   209  			if err != nil {
   210  				return err
   211  			}
   212  			var nextra int64
   213  			nextra, err = io.Copy(ioutil.Discard, t.Body)
   214  			ncopy += nextra
   215  		}
   216  		if err != nil {
   217  			return err
   218  		}
   219  		if err = t.BodyCloser.Close(); err != nil {
   220  			return err
   221  		}
   222  	}
   223  
   224  	if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
   225  		return fmt.Errorf("http: ContentLength=%d with Body length %d",
   226  			t.ContentLength, ncopy)
   227  	}
   228  
   229  	if chunked(t.TransferEncoding) {
   230  		// Write Trailer header
   231  		if t.Trailer != nil {
   232  			if err := t.Trailer.Write(w); err != nil {
   233  				return err
   234  			}
   235  		}
   236  		// Last chunk, empty trailer
   237  		_, err = io.WriteString(w, "\r\n")
   238  	}
   239  	return err
   240  }
   241  
   242  type transferReader struct {
   243  	// Input
   244  	Header        Header
   245  	StatusCode    int
   246  	RequestMethod string
   247  	ProtoMajor    int
   248  	ProtoMinor    int
   249  	// Output
   250  	Body             io.ReadCloser
   251  	ContentLength    int64
   252  	TransferEncoding []string
   253  	Close            bool
   254  	Trailer          Header
   255  }
   256  
   257  func (t *transferReader) protoAtLeast(m, n int) bool {
   258  	return t.ProtoMajor > m || (t.ProtoMajor == m && t.ProtoMinor >= n)
   259  }
   260  
   261  // bodyAllowedForStatus reports whether a given response status code
   262  // permits a body. See RFC 2616, section 4.4.
   263  func bodyAllowedForStatus(status int) bool {
   264  	switch {
   265  	case status >= 100 && status <= 199:
   266  		return false
   267  	case status == 204:
   268  		return false
   269  	case status == 304:
   270  		return false
   271  	}
   272  	return true
   273  }
   274  
   275  var (
   276  	suppressedHeaders304    = []string{"Content-Type", "Content-Length", "Transfer-Encoding"}
   277  	suppressedHeadersNoBody = []string{"Content-Length", "Transfer-Encoding"}
   278  )
   279  
   280  func suppressedHeaders(status int) []string {
   281  	switch {
   282  	case status == 304:
   283  		// RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers"
   284  		return suppressedHeaders304
   285  	case !bodyAllowedForStatus(status):
   286  		return suppressedHeadersNoBody
   287  	}
   288  	return nil
   289  }
   290  
   291  // msg is *Request or *Response.
   292  func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
   293  	t := &transferReader{RequestMethod: "GET"}
   294  
   295  	// Unify input
   296  	isResponse := false
   297  	switch rr := msg.(type) {
   298  	case *Response:
   299  		t.Header = rr.Header
   300  		t.StatusCode = rr.StatusCode
   301  		t.ProtoMajor = rr.ProtoMajor
   302  		t.ProtoMinor = rr.ProtoMinor
   303  		t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header, true)
   304  		isResponse = true
   305  		if rr.Request != nil {
   306  			t.RequestMethod = rr.Request.Method
   307  		}
   308  	case *Request:
   309  		t.Header = rr.Header
   310  		t.RequestMethod = rr.Method
   311  		t.ProtoMajor = rr.ProtoMajor
   312  		t.ProtoMinor = rr.ProtoMinor
   313  		// Transfer semantics for Requests are exactly like those for
   314  		// Responses with status code 200, responding to a GET method
   315  		t.StatusCode = 200
   316  		t.Close = rr.Close
   317  	default:
   318  		panic("unexpected type")
   319  	}
   320  
   321  	// Default to HTTP/1.1
   322  	if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
   323  		t.ProtoMajor, t.ProtoMinor = 1, 1
   324  	}
   325  
   326  	// Transfer encoding, content length
   327  	err = t.fixTransferEncoding()
   328  	if err != nil {
   329  		return err
   330  	}
   331  
   332  	realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
   333  	if err != nil {
   334  		return err
   335  	}
   336  	if isResponse && t.RequestMethod == "HEAD" {
   337  		if n, err := parseContentLength(t.Header.get("Content-Length")); err != nil {
   338  			return err
   339  		} else {
   340  			t.ContentLength = n
   341  		}
   342  	} else {
   343  		t.ContentLength = realLength
   344  	}
   345  
   346  	// Trailer
   347  	t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
   348  	if err != nil {
   349  		return err
   350  	}
   351  
   352  	// If there is no Content-Length or chunked Transfer-Encoding on a *Response
   353  	// and the status is not 1xx, 204 or 304, then the body is unbounded.
   354  	// See RFC 2616, section 4.4.
   355  	switch msg.(type) {
   356  	case *Response:
   357  		if realLength == -1 &&
   358  			!chunked(t.TransferEncoding) &&
   359  			bodyAllowedForStatus(t.StatusCode) {
   360  			// Unbounded body.
   361  			t.Close = true
   362  		}
   363  	}
   364  
   365  	// Prepare body reader. ContentLength < 0 means chunked encoding
   366  	// or close connection when finished, since multipart is not supported yet
   367  	switch {
   368  	case chunked(t.TransferEncoding):
   369  		if noBodyExpected(t.RequestMethod) {
   370  			t.Body = NoBody
   371  		} else {
   372  			t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
   373  		}
   374  	case realLength == 0:
   375  		t.Body = NoBody
   376  	case realLength > 0:
   377  		t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
   378  	default:
   379  		// realLength < 0, i.e. "Content-Length" not mentioned in header
   380  		if t.Close {
   381  			// Close semantics (i.e. HTTP/1.0)
   382  			t.Body = &body{src: r, closing: t.Close}
   383  		} else {
   384  			// Persistent connection (i.e. HTTP/1.1)
   385  			t.Body = NoBody
   386  		}
   387  	}
   388  
   389  	// Unify output
   390  	switch rr := msg.(type) {
   391  	case *Request:
   392  		rr.Body = t.Body
   393  		rr.ContentLength = t.ContentLength
   394  		rr.TransferEncoding = t.TransferEncoding
   395  		rr.Close = t.Close
   396  		rr.Trailer = t.Trailer
   397  	case *Response:
   398  		rr.Body = t.Body
   399  		rr.ContentLength = t.ContentLength
   400  		rr.TransferEncoding = t.TransferEncoding
   401  		rr.Close = t.Close
   402  		rr.Trailer = t.Trailer
   403  	}
   404  
   405  	return nil
   406  }
   407  
   408  // Checks whether chunked is part of the encodings stack
   409  func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
   410  
   411  // Checks whether the encoding is explicitly "identity".
   412  func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
   413  
   414  // fixTransferEncoding sanitizes t.TransferEncoding, if needed.
   415  func (t *transferReader) fixTransferEncoding() error {
   416  	raw, present := t.Header["Transfer-Encoding"]
   417  	if !present {
   418  		return nil
   419  	}
   420  	delete(t.Header, "Transfer-Encoding")
   421  
   422  	// Issue 12785; ignore Transfer-Encoding on HTTP/1.0 requests.
   423  	if !t.protoAtLeast(1, 1) {
   424  		return nil
   425  	}
   426  
   427  	encodings := strings.Split(raw[0], ",")
   428  	te := make([]string, 0, len(encodings))
   429  	// TODO: Even though we only support "identity" and "chunked"
   430  	// encodings, the loop below is designed with foresight. One
   431  	// invariant that must be maintained is that, if present,
   432  	// chunked encoding must always come first.
   433  	for _, encoding := range encodings {
   434  		encoding = strings.ToLower(strings.TrimSpace(encoding))
   435  		// "identity" encoding is not recorded
   436  		if encoding == "identity" {
   437  			break
   438  		}
   439  		if encoding != "chunked" {
   440  			return &badStringError{"unsupported transfer encoding", encoding}
   441  		}
   442  		te = te[0 : len(te)+1]
   443  		te[len(te)-1] = encoding
   444  	}
   445  	if len(te) > 1 {
   446  		return &badStringError{"too many transfer encodings", strings.Join(te, ",")}
   447  	}
   448  	if len(te) > 0 {
   449  		// RFC 7230 3.3.2 says "A sender MUST NOT send a
   450  		// Content-Length header field in any message that
   451  		// contains a Transfer-Encoding header field."
   452  		//
   453  		// but also:
   454  		// "If a message is received with both a
   455  		// Transfer-Encoding and a Content-Length header
   456  		// field, the Transfer-Encoding overrides the
   457  		// Content-Length. Such a message might indicate an
   458  		// attempt to perform request smuggling (Section 9.5)
   459  		// or response splitting (Section 9.4) and ought to be
   460  		// handled as an error. A sender MUST remove the
   461  		// received Content-Length field prior to forwarding
   462  		// such a message downstream."
   463  		//
   464  		// Reportedly, these appear in the wild.
   465  		delete(t.Header, "Content-Length")
   466  		t.TransferEncoding = te
   467  		return nil
   468  	}
   469  
   470  	return nil
   471  }
   472  
   473  // Determine the expected body length, using RFC 2616 Section 4.4. This
   474  // function is not a method, because ultimately it should be shared by
   475  // ReadResponse and ReadRequest.
   476  func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) {
   477  	isRequest := !isResponse
   478  	contentLens := header["Content-Length"]
   479  
   480  	// Hardening against HTTP request smuggling
   481  	if len(contentLens) > 1 {
   482  		// Per RFC 7230 Section 3.3.2, prevent multiple
   483  		// Content-Length headers if they differ in value.
   484  		// If there are dups of the value, remove the dups.
   485  		// See Issue 16490.
   486  		first := strings.TrimSpace(contentLens[0])
   487  		for _, ct := range contentLens[1:] {
   488  			if first != strings.TrimSpace(ct) {
   489  				return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", contentLens)
   490  			}
   491  		}
   492  
   493  		// deduplicate Content-Length
   494  		header.Del("Content-Length")
   495  		header.Add("Content-Length", first)
   496  
   497  		contentLens = header["Content-Length"]
   498  	}
   499  
   500  	// Logic based on response type or status
   501  	if noBodyExpected(requestMethod) {
   502  		// For HTTP requests, as part of hardening against request
   503  		// smuggling (RFC 7230), don't allow a Content-Length header for
   504  		// methods which don't permit bodies. As an exception, allow
   505  		// exactly one Content-Length header if its value is "0".
   506  		if isRequest && len(contentLens) > 0 && !(len(contentLens) == 1 && contentLens[0] == "0") {
   507  			return 0, fmt.Errorf("http: method cannot contain a Content-Length; got %q", contentLens)
   508  		}
   509  		return 0, nil
   510  	}
   511  	if status/100 == 1 {
   512  		return 0, nil
   513  	}
   514  	switch status {
   515  	case 204, 304:
   516  		return 0, nil
   517  	}
   518  
   519  	// Logic based on Transfer-Encoding
   520  	if chunked(te) {
   521  		return -1, nil
   522  	}
   523  
   524  	// Logic based on Content-Length
   525  	var cl string
   526  	if len(contentLens) == 1 {
   527  		cl = strings.TrimSpace(contentLens[0])
   528  	}
   529  	if cl != "" {
   530  		n, err := parseContentLength(cl)
   531  		if err != nil {
   532  			return -1, err
   533  		}
   534  		return n, nil
   535  	} else {
   536  		header.Del("Content-Length")
   537  	}
   538  
   539  	if isRequest {
   540  		// RFC 2616 neither explicitly permits nor forbids an
   541  		// entity-body on a GET request so we permit one if
   542  		// declared, but we default to 0 here (not -1 below)
   543  		// if there's no mention of a body.
   544  		// Likewise, all other request methods are assumed to have
   545  		// no body if neither Transfer-Encoding chunked nor a
   546  		// Content-Length are set.
   547  		return 0, nil
   548  	}
   549  
   550  	// Body-EOF logic based on other methods (like closing, or chunked coding)
   551  	return -1, nil
   552  }
   553  
   554  // Determine whether to hang up after sending a request and body, or
   555  // receiving a response and body
   556  // 'header' is the request headers
   557  func shouldClose(major, minor int, header Header, removeCloseHeader bool) bool {
   558  	if major < 1 {
   559  		return true
   560  	}
   561  
   562  	conv := header["Connection"]
   563  	hasClose := httplex.HeaderValuesContainsToken(conv, "close")
   564  	if major == 1 && minor == 0 {
   565  		return hasClose || !httplex.HeaderValuesContainsToken(conv, "keep-alive")
   566  	}
   567  
   568  	if hasClose && removeCloseHeader {
   569  		header.Del("Connection")
   570  	}
   571  
   572  	return hasClose
   573  }
   574  
   575  // Parse the trailer header
   576  func fixTrailer(header Header, te []string) (Header, error) {
   577  	vv, ok := header["Trailer"]
   578  	if !ok {
   579  		return nil, nil
   580  	}
   581  	header.Del("Trailer")
   582  
   583  	trailer := make(Header)
   584  	var err error
   585  	for _, v := range vv {
   586  		foreachHeaderElement(v, func(key string) {
   587  			key = CanonicalHeaderKey(key)
   588  			switch key {
   589  			case "Transfer-Encoding", "Trailer", "Content-Length":
   590  				if err == nil {
   591  					err = &badStringError{"bad trailer key", key}
   592  					return
   593  				}
   594  			}
   595  			trailer[key] = nil
   596  		})
   597  	}
   598  	if err != nil {
   599  		return nil, err
   600  	}
   601  	if len(trailer) == 0 {
   602  		return nil, nil
   603  	}
   604  	if !chunked(te) {
   605  		// Trailer and no chunking
   606  		return nil, ErrUnexpectedTrailer
   607  	}
   608  	return trailer, nil
   609  }
   610  
   611  // body turns a Reader into a ReadCloser.
   612  // Close ensures that the body has been fully read
   613  // and then reads the trailer if necessary.
   614  type body struct {
   615  	src          io.Reader
   616  	hdr          interface{}   // non-nil (Response or Request) value means read trailer
   617  	r            *bufio.Reader // underlying wire-format reader for the trailer
   618  	closing      bool          // is the connection to be closed after reading body?
   619  	doEarlyClose bool          // whether Close should stop early
   620  
   621  	mu         sync.Mutex // guards following, and calls to Read and Close
   622  	sawEOF     bool
   623  	closed     bool
   624  	earlyClose bool   // Close called and we didn't read to the end of src
   625  	onHitEOF   func() // if non-nil, func to call when EOF is Read
   626  }
   627  
   628  // ErrBodyReadAfterClose is returned when reading a Request or Response
   629  // Body after the body has been closed. This typically happens when the body is
   630  // read after an HTTP Handler calls WriteHeader or Write on its
   631  // ResponseWriter.
   632  var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
   633  
   634  func (b *body) Read(p []byte) (n int, err error) {
   635  	b.mu.Lock()
   636  	defer b.mu.Unlock()
   637  	if b.closed {
   638  		return 0, ErrBodyReadAfterClose
   639  	}
   640  	return b.readLocked(p)
   641  }
   642  
   643  // Must hold b.mu.
   644  func (b *body) readLocked(p []byte) (n int, err error) {
   645  	if b.sawEOF {
   646  		return 0, io.EOF
   647  	}
   648  	n, err = b.src.Read(p)
   649  
   650  	if err == io.EOF {
   651  		b.sawEOF = true
   652  		// Chunked case. Read the trailer.
   653  		if b.hdr != nil {
   654  			if e := b.readTrailer(); e != nil {
   655  				err = e
   656  				// Something went wrong in the trailer, we must not allow any
   657  				// further reads of any kind to succeed from body, nor any
   658  				// subsequent requests on the server connection. See
   659  				// golang.org/issue/12027
   660  				b.sawEOF = false
   661  				b.closed = true
   662  			}
   663  			b.hdr = nil
   664  		} else {
   665  			// If the server declared the Content-Length, our body is a LimitedReader
   666  			// and we need to check whether this EOF arrived early.
   667  			if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > 0 {
   668  				err = io.ErrUnexpectedEOF
   669  			}
   670  		}
   671  	}
   672  
   673  	// If we can return an EOF here along with the read data, do
   674  	// so. This is optional per the io.Reader contract, but doing
   675  	// so helps the HTTP transport code recycle its connection
   676  	// earlier (since it will see this EOF itself), even if the
   677  	// client doesn't do future reads or Close.
   678  	if err == nil && n > 0 {
   679  		if lr, ok := b.src.(*io.LimitedReader); ok && lr.N == 0 {
   680  			err = io.EOF
   681  			b.sawEOF = true
   682  		}
   683  	}
   684  
   685  	if b.sawEOF && b.onHitEOF != nil {
   686  		b.onHitEOF()
   687  	}
   688  
   689  	return n, err
   690  }
   691  
   692  var (
   693  	singleCRLF = []byte("\r\n")
   694  	doubleCRLF = []byte("\r\n\r\n")
   695  )
   696  
   697  func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
   698  	for peekSize := 4; ; peekSize++ {
   699  		// This loop stops when Peek returns an error,
   700  		// which it does when r's buffer has been filled.
   701  		buf, err := r.Peek(peekSize)
   702  		if bytes.HasSuffix(buf, doubleCRLF) {
   703  			return true
   704  		}
   705  		if err != nil {
   706  			break
   707  		}
   708  	}
   709  	return false
   710  }
   711  
   712  var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
   713  
   714  func (b *body) readTrailer() error {
   715  	// The common case, since nobody uses trailers.
   716  	buf, err := b.r.Peek(2)
   717  	if bytes.Equal(buf, singleCRLF) {
   718  		b.r.Discard(2)
   719  		return nil
   720  	}
   721  	if len(buf) < 2 {
   722  		return errTrailerEOF
   723  	}
   724  	if err != nil {
   725  		return err
   726  	}
   727  
   728  	// Make sure there's a header terminator coming up, to prevent
   729  	// a DoS with an unbounded size Trailer. It's not easy to
   730  	// slip in a LimitReader here, as textproto.NewReader requires
   731  	// a concrete *bufio.Reader. Also, we can't get all the way
   732  	// back up to our conn's LimitedReader that *might* be backing
   733  	// this bufio.Reader. Instead, a hack: we iteratively Peek up
   734  	// to the bufio.Reader's max size, looking for a double CRLF.
   735  	// This limits the trailer to the underlying buffer size, typically 4kB.
   736  	if !seeUpcomingDoubleCRLF(b.r) {
   737  		return errors.New("http: suspiciously long trailer after chunked body")
   738  	}
   739  
   740  	hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
   741  	if err != nil {
   742  		if err == io.EOF {
   743  			return errTrailerEOF
   744  		}
   745  		return err
   746  	}
   747  	switch rr := b.hdr.(type) {
   748  	case *Request:
   749  		mergeSetHeader(&rr.Trailer, Header(hdr))
   750  	case *Response:
   751  		mergeSetHeader(&rr.Trailer, Header(hdr))
   752  	}
   753  	return nil
   754  }
   755  
   756  func mergeSetHeader(dst *Header, src Header) {
   757  	if *dst == nil {
   758  		*dst = src
   759  		return
   760  	}
   761  	for k, vv := range src {
   762  		(*dst)[k] = vv
   763  	}
   764  }
   765  
   766  // unreadDataSizeLocked returns the number of bytes of unread input.
   767  // It returns -1 if unknown.
   768  // b.mu must be held.
   769  func (b *body) unreadDataSizeLocked() int64 {
   770  	if lr, ok := b.src.(*io.LimitedReader); ok {
   771  		return lr.N
   772  	}
   773  	return -1
   774  }
   775  
   776  func (b *body) Close() error {
   777  	b.mu.Lock()
   778  	defer b.mu.Unlock()
   779  	if b.closed {
   780  		return nil
   781  	}
   782  	var err error
   783  	switch {
   784  	case b.sawEOF:
   785  		// Already saw EOF, so no need going to look for it.
   786  	case b.hdr == nil && b.closing:
   787  		// no trailer and closing the connection next.
   788  		// no point in reading to EOF.
   789  	case b.doEarlyClose:
   790  		// Read up to maxPostHandlerReadBytes bytes of the body, looking for
   791  		// for EOF (and trailers), so we can re-use this connection.
   792  		if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > maxPostHandlerReadBytes {
   793  			// There was a declared Content-Length, and we have more bytes remaining
   794  			// than our maxPostHandlerReadBytes tolerance. So, give up.
   795  			b.earlyClose = true
   796  		} else {
   797  			var n int64
   798  			// Consume the body, or, which will also lead to us reading
   799  			// the trailer headers after the body, if present.
   800  			n, err = io.CopyN(ioutil.Discard, bodyLocked{b}, maxPostHandlerReadBytes)
   801  			if err == io.EOF {
   802  				err = nil
   803  			}
   804  			if n == maxPostHandlerReadBytes {
   805  				b.earlyClose = true
   806  			}
   807  		}
   808  	default:
   809  		// Fully consume the body, which will also lead to us reading
   810  		// the trailer headers after the body, if present.
   811  		_, err = io.Copy(ioutil.Discard, bodyLocked{b})
   812  	}
   813  	b.closed = true
   814  	return err
   815  }
   816  
   817  func (b *body) didEarlyClose() bool {
   818  	b.mu.Lock()
   819  	defer b.mu.Unlock()
   820  	return b.earlyClose
   821  }
   822  
   823  // bodyRemains reports whether future Read calls might
   824  // yield data.
   825  func (b *body) bodyRemains() bool {
   826  	b.mu.Lock()
   827  	defer b.mu.Unlock()
   828  	return !b.sawEOF
   829  }
   830  
   831  func (b *body) registerOnHitEOF(fn func()) {
   832  	b.mu.Lock()
   833  	defer b.mu.Unlock()
   834  	b.onHitEOF = fn
   835  }
   836  
   837  // bodyLocked is a io.Reader reading from a *body when its mutex is
   838  // already held.
   839  type bodyLocked struct {
   840  	b *body
   841  }
   842  
   843  func (bl bodyLocked) Read(p []byte) (n int, err error) {
   844  	if bl.b.closed {
   845  		return 0, ErrBodyReadAfterClose
   846  	}
   847  	return bl.b.readLocked(p)
   848  }
   849  
   850  // parseContentLength trims whitespace from s and returns -1 if no value
   851  // is set, or the value if it's >= 0.
   852  func parseContentLength(cl string) (int64, error) {
   853  	cl = strings.TrimSpace(cl)
   854  	if cl == "" {
   855  		return -1, nil
   856  	}
   857  	n, err := strconv.ParseInt(cl, 10, 64)
   858  	if err != nil || n < 0 {
   859  		return 0, &badStringError{"bad Content-Length", cl}
   860  	}
   861  	return n, nil
   862  
   863  }