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.
21 "golang_org/x/net/lex/httplex"
24 // ErrLineTooLong is returned when reading request or response bodies
25 // with malformed chunked encoding.
26 var ErrLineTooLong = internal.ErrLineTooLong
28 type errorReader struct {
32 func (r errorReader) Read(p []byte) (n int, err error) {
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 {
44 ContentLength int64 // -1 means unknown, 0 means exactly none
46 TransferEncoding []string
51 func newTransferWriter(r interface{}) (t *transferWriter, err error) {
54 // Extract relevant fields
55 atLeastHTTP11 := false
56 switch rr := r.(type) {
58 if rr.ContentLength != 0 && rr.Body == nil {
59 return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
61 t.Method = valueOrDefault(rr.Method, "GET")
63 t.TransferEncoding = rr.TransferEncoding
64 t.Trailer = rr.Trailer
65 atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
68 t.ContentLength = rr.outgoingLength()
70 t.BodyCloser = rr.Body
72 if t.ContentLength < 0 && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
73 t.TransferEncoding = []string{"chunked"}
77 if rr.Request != nil {
78 t.Method = rr.Request.Method
81 t.BodyCloser = rr.Body
82 t.ContentLength = rr.ContentLength
84 t.TransferEncoding = rr.TransferEncoding
85 t.Trailer = rr.Trailer
86 atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
87 t.ResponseToHEAD = noBodyExpected(t.Method)
90 // Sanitize Body,ContentLength,TransferEncoding
93 if chunked(t.TransferEncoding) {
97 if !atLeastHTTP11 || t.Body == nil {
98 t.TransferEncoding = nil
100 if chunked(t.TransferEncoding) {
102 } else if t.Body == nil { // no chunking, no body
108 if !chunked(t.TransferEncoding) {
115 func noBodyExpected(requestMethod string) bool {
116 return requestMethod == "HEAD"
119 func (t *transferWriter) shouldSendContentLength() bool {
120 if chunked(t.TransferEncoding) {
123 if t.ContentLength > 0 {
126 if t.ContentLength < 0 {
129 // Many servers expect a Content-Length for these methods
130 if t.Method == "POST" || t.Method == "PUT" {
133 if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
134 if t.Method == "GET" || t.Method == "HEAD" {
143 func (t *transferWriter) WriteHeader(w io.Writer) error {
145 if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
150 // Write Content-Length and/or Transfer-Encoding whose values are a
151 // function of the sanitized field triple (Body, ContentLength,
153 if t.shouldSendContentLength() {
154 if _, err := io.WriteString(w, "Content-Length: "); err != nil {
157 if _, err := io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n"); err != nil {
160 } else if chunked(t.TransferEncoding) {
161 if _, err := io.WriteString(w, "Transfer-Encoding: chunked\r\n"); err != nil {
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)
172 case "Transfer-Encoding", "Trailer", "Content-Length":
173 return &badStringError{"invalid Trailer key", k}
175 keys = append(keys, k)
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 {
190 func (t *transferWriter) WriteBody(w io.Writer) error {
196 if chunked(t.TransferEncoding) {
197 if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
198 w = &internal.FlushAfterChunkWriter{Writer: bw}
200 cw := internal.NewChunkedWriter(w)
201 _, err = io.Copy(cw, t.Body)
205 } else if t.ContentLength == -1 {
206 ncopy, err = io.Copy(w, t.Body)
208 ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
213 nextra, err = io.Copy(ioutil.Discard, t.Body)
219 if err = t.BodyCloser.Close(); err != nil {
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)
229 if chunked(t.TransferEncoding) {
230 // Write Trailer header
231 if t.Trailer != nil {
232 if err := t.Trailer.Write(w); err != nil {
236 // Last chunk, empty trailer
237 _, err = io.WriteString(w, "\r\n")
242 type transferReader struct {
252 TransferEncoding []string
257 func (t *transferReader) protoAtLeast(m, n int) bool {
258 return t.ProtoMajor > m || (t.ProtoMajor == m && t.ProtoMinor >= n)
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 {
265 case status >= 100 && status <= 199:
276 suppressedHeaders304 = []string{"Content-Type", "Content-Length", "Transfer-Encoding"}
277 suppressedHeadersNoBody = []string{"Content-Length", "Transfer-Encoding"}
280 func suppressedHeaders(status int) []string {
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
291 // msg is *Request or *Response.
292 func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
293 t := &transferReader{RequestMethod: "GET"}
297 switch rr := msg.(type) {
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)
305 if rr.Request != nil {
306 t.RequestMethod = rr.Request.Method
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
318 panic("unexpected type")
321 // Default to HTTP/1.1
322 if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
323 t.ProtoMajor, t.ProtoMinor = 1, 1
326 // Transfer encoding, content length
327 err = t.fixTransferEncoding()
332 realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
336 if isResponse && t.RequestMethod == "HEAD" {
337 if n, err := parseContentLength(t.Header.get("Content-Length")); err != nil {
343 t.ContentLength = realLength
347 t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
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.
357 if realLength == -1 &&
358 !chunked(t.TransferEncoding) &&
359 bodyAllowedForStatus(t.StatusCode) {
365 // Prepare body reader. ContentLength < 0 means chunked encoding
366 // or close connection when finished, since multipart is not supported yet
368 case chunked(t.TransferEncoding):
369 if noBodyExpected(t.RequestMethod) {
372 t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
374 case realLength == 0:
377 t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
379 // realLength < 0, i.e. "Content-Length" not mentioned in header
381 // Close semantics (i.e. HTTP/1.0)
382 t.Body = &body{src: r, closing: t.Close}
384 // Persistent connection (i.e. HTTP/1.1)
390 switch rr := msg.(type) {
393 rr.ContentLength = t.ContentLength
394 rr.TransferEncoding = t.TransferEncoding
396 rr.Trailer = t.Trailer
399 rr.ContentLength = t.ContentLength
400 rr.TransferEncoding = t.TransferEncoding
402 rr.Trailer = t.Trailer
408 // Checks whether chunked is part of the encodings stack
409 func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
411 // Checks whether the encoding is explicitly "identity".
412 func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
414 // fixTransferEncoding sanitizes t.TransferEncoding, if needed.
415 func (t *transferReader) fixTransferEncoding() error {
416 raw, present := t.Header["Transfer-Encoding"]
420 delete(t.Header, "Transfer-Encoding")
422 // Issue 12785; ignore Transfer-Encoding on HTTP/1.0 requests.
423 if !t.protoAtLeast(1, 1) {
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" {
439 if encoding != "chunked" {
440 return &badStringError{"unsupported transfer encoding", encoding}
442 te = te[0 : len(te)+1]
443 te[len(te)-1] = encoding
446 return &badStringError{"too many transfer encodings", strings.Join(te, ",")}
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."
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."
464 // Reportedly, these appear in the wild.
465 delete(t.Header, "Content-Length")
466 t.TransferEncoding = te
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"]
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.
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)
493 // deduplicate Content-Length
494 header.Del("Content-Length")
495 header.Add("Content-Length", first)
497 contentLens = header["Content-Length"]
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)
519 // Logic based on Transfer-Encoding
524 // Logic based on Content-Length
526 if len(contentLens) == 1 {
527 cl = strings.TrimSpace(contentLens[0])
530 n, err := parseContentLength(cl)
536 header.Del("Content-Length")
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.
550 // Body-EOF logic based on other methods (like closing, or chunked coding)
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 {
562 conv := header["Connection"]
563 hasClose := httplex.HeaderValuesContainsToken(conv, "close")
564 if major == 1 && minor == 0 {
565 return hasClose || !httplex.HeaderValuesContainsToken(conv, "keep-alive")
568 if hasClose && removeCloseHeader {
569 header.Del("Connection")
575 // Parse the trailer header
576 func fixTrailer(header Header, te []string) (Header, error) {
577 vv, ok := header["Trailer"]
581 header.Del("Trailer")
583 trailer := make(Header)
585 for _, v := range vv {
586 foreachHeaderElement(v, func(key string) {
587 key = CanonicalHeaderKey(key)
589 case "Transfer-Encoding", "Trailer", "Content-Length":
591 err = &badStringError{"bad trailer key", key}
601 if len(trailer) == 0 {
605 // Trailer and no chunking
606 return nil, ErrUnexpectedTrailer
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.
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
621 mu sync.Mutex // guards following, and calls to Read and Close
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
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
632 var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
634 func (b *body) Read(p []byte) (n int, err error) {
638 return 0, ErrBodyReadAfterClose
640 return b.readLocked(p)
644 func (b *body) readLocked(p []byte) (n int, err error) {
648 n, err = b.src.Read(p)
652 // Chunked case. Read the trailer.
654 if e := b.readTrailer(); e != nil {
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
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
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 {
685 if b.sawEOF && b.onHitEOF != nil {
693 singleCRLF = []byte("\r\n")
694 doubleCRLF = []byte("\r\n\r\n")
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) {
712 var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
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) {
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")
740 hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
747 switch rr := b.hdr.(type) {
749 mergeSetHeader(&rr.Trailer, Header(hdr))
751 mergeSetHeader(&rr.Trailer, Header(hdr))
756 func mergeSetHeader(dst *Header, src Header) {
761 for k, vv := range src {
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 {
776 func (b *body) Close() error {
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.
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.
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)
804 if n == maxPostHandlerReadBytes {
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})
817 func (b *body) didEarlyClose() bool {
823 // bodyRemains reports whether future Read calls might
825 func (b *body) bodyRemains() bool {
831 func (b *body) registerOnHitEOF(fn func()) {
837 // bodyLocked is a io.Reader reading from a *body when its mutex is
839 type bodyLocked struct {
843 func (bl bodyLocked) Read(p []byte) (n int, err error) {
845 return 0, ErrBodyReadAfterClose
847 return bl.b.readLocked(p)
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)
857 n, err := strconv.ParseInt(cl, 10, 64)
858 if err != nil || n < 0 {
859 return 0, &badStringError{"bad Content-Length", cl}