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