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