Rebase.
[official-gcc.git] / libgo / go / net / http / transfer.go
blob7f63686528aae75edca37ffbf3cdde4745e63b6c
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.
5 package http
7 import (
8 "bufio"
9 "bytes"
10 "errors"
11 "fmt"
12 "io"
13 "io/ioutil"
14 "net/textproto"
15 "sort"
16 "strconv"
17 "strings"
18 "sync"
21 type errorReader struct {
22 err error
25 func (r *errorReader) Read(p []byte) (n int, err error) {
26 return 0, r.err
29 // transferWriter inspects the fields of a user-supplied Request or Response,
30 // sanitizes them without changing the user object and provides methods for
31 // writing the respective header, body and trailer in wire format.
32 type transferWriter struct {
33 Method string
34 Body io.Reader
35 BodyCloser io.Closer
36 ResponseToHEAD bool
37 ContentLength int64 // -1 means unknown, 0 means exactly none
38 Close bool
39 TransferEncoding []string
40 Trailer Header
43 func newTransferWriter(r interface{}) (t *transferWriter, err error) {
44 t = &transferWriter{}
46 // Extract relevant fields
47 atLeastHTTP11 := false
48 switch rr := r.(type) {
49 case *Request:
50 if rr.ContentLength != 0 && rr.Body == nil {
51 return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
53 t.Method = rr.Method
54 t.Body = rr.Body
55 t.BodyCloser = rr.Body
56 t.ContentLength = rr.ContentLength
57 t.Close = rr.Close
58 t.TransferEncoding = rr.TransferEncoding
59 t.Trailer = rr.Trailer
60 atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
61 if t.Body != nil && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
62 if t.ContentLength == 0 {
63 // Test to see if it's actually zero or just unset.
64 var buf [1]byte
65 n, rerr := io.ReadFull(t.Body, buf[:])
66 if rerr != nil && rerr != io.EOF {
67 t.ContentLength = -1
68 t.Body = &errorReader{rerr}
69 } else if n == 1 {
70 // Oh, guess there is data in this Body Reader after all.
71 // The ContentLength field just wasn't set.
72 // Stich the Body back together again, re-attaching our
73 // consumed byte.
74 t.ContentLength = -1
75 t.Body = io.MultiReader(bytes.NewReader(buf[:]), t.Body)
76 } else {
77 // Body is actually empty.
78 t.Body = nil
79 t.BodyCloser = nil
82 if t.ContentLength < 0 {
83 t.TransferEncoding = []string{"chunked"}
86 case *Response:
87 if rr.Request != nil {
88 t.Method = rr.Request.Method
90 t.Body = rr.Body
91 t.BodyCloser = rr.Body
92 t.ContentLength = rr.ContentLength
93 t.Close = rr.Close
94 t.TransferEncoding = rr.TransferEncoding
95 t.Trailer = rr.Trailer
96 atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
97 t.ResponseToHEAD = noBodyExpected(t.Method)
100 // Sanitize Body,ContentLength,TransferEncoding
101 if t.ResponseToHEAD {
102 t.Body = nil
103 if chunked(t.TransferEncoding) {
104 t.ContentLength = -1
106 } else {
107 if !atLeastHTTP11 || t.Body == nil {
108 t.TransferEncoding = nil
110 if chunked(t.TransferEncoding) {
111 t.ContentLength = -1
112 } else if t.Body == nil { // no chunking, no body
113 t.ContentLength = 0
117 // Sanitize Trailer
118 if !chunked(t.TransferEncoding) {
119 t.Trailer = nil
122 return t, nil
125 func noBodyExpected(requestMethod string) bool {
126 return requestMethod == "HEAD"
129 func (t *transferWriter) shouldSendContentLength() bool {
130 if chunked(t.TransferEncoding) {
131 return false
133 if t.ContentLength > 0 {
134 return true
136 // Many servers expect a Content-Length for these methods
137 if t.Method == "POST" || t.Method == "PUT" {
138 return true
140 if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
141 return true
144 return false
147 func (t *transferWriter) WriteHeader(w io.Writer) error {
148 if t.Close {
149 if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
150 return err
154 // Write Content-Length and/or Transfer-Encoding whose values are a
155 // function of the sanitized field triple (Body, ContentLength,
156 // TransferEncoding)
157 if t.shouldSendContentLength() {
158 if _, err := io.WriteString(w, "Content-Length: "); err != nil {
159 return err
161 if _, err := io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n"); err != nil {
162 return err
164 } else if chunked(t.TransferEncoding) {
165 if _, err := io.WriteString(w, "Transfer-Encoding: chunked\r\n"); err != nil {
166 return err
170 // Write Trailer header
171 if t.Trailer != nil {
172 keys := make([]string, 0, len(t.Trailer))
173 for k := range t.Trailer {
174 k = CanonicalHeaderKey(k)
175 switch k {
176 case "Transfer-Encoding", "Trailer", "Content-Length":
177 return &badStringError{"invalid Trailer key", k}
179 keys = append(keys, k)
181 if len(keys) > 0 {
182 sort.Strings(keys)
183 // TODO: could do better allocation-wise here, but trailers are rare,
184 // so being lazy for now.
185 if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
186 return err
191 return nil
194 func (t *transferWriter) WriteBody(w io.Writer) error {
195 var err error
196 var ncopy int64
198 // Write body
199 if t.Body != nil {
200 if chunked(t.TransferEncoding) {
201 cw := newChunkedWriter(w)
202 _, err = io.Copy(cw, t.Body)
203 if err == nil {
204 err = cw.Close()
206 } else if t.ContentLength == -1 {
207 ncopy, err = io.Copy(w, t.Body)
208 } else {
209 ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
210 if err != nil {
211 return err
213 var nextra int64
214 nextra, err = io.Copy(ioutil.Discard, t.Body)
215 ncopy += nextra
217 if err != nil {
218 return err
220 if err = t.BodyCloser.Close(); err != nil {
221 return err
225 if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
226 return fmt.Errorf("http: Request.ContentLength=%d with Body length %d",
227 t.ContentLength, ncopy)
230 // TODO(petar): Place trailer writer code here.
231 if chunked(t.TransferEncoding) {
232 // Write Trailer header
233 if t.Trailer != nil {
234 if err := t.Trailer.Write(w); err != nil {
235 return err
238 // Last chunk, empty trailer
239 _, err = io.WriteString(w, "\r\n")
241 return err
244 type transferReader struct {
245 // Input
246 Header Header
247 StatusCode int
248 RequestMethod string
249 ProtoMajor int
250 ProtoMinor int
251 // Output
252 Body io.ReadCloser
253 ContentLength int64
254 TransferEncoding []string
255 Close bool
256 Trailer Header
259 // bodyAllowedForStatus reports whether a given response status code
260 // permits a body. See RFC2616, section 4.4.
261 func bodyAllowedForStatus(status int) bool {
262 switch {
263 case status >= 100 && status <= 199:
264 return false
265 case status == 204:
266 return false
267 case status == 304:
268 return false
270 return true
273 var (
274 suppressedHeaders304 = []string{"Content-Type", "Content-Length", "Transfer-Encoding"}
275 suppressedHeadersNoBody = []string{"Content-Length", "Transfer-Encoding"}
278 func suppressedHeaders(status int) []string {
279 switch {
280 case status == 304:
281 // RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers"
282 return suppressedHeaders304
283 case !bodyAllowedForStatus(status):
284 return suppressedHeadersNoBody
286 return nil
289 // msg is *Request or *Response.
290 func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
291 t := &transferReader{RequestMethod: "GET"}
293 // Unify input
294 isResponse := false
295 switch rr := msg.(type) {
296 case *Response:
297 t.Header = rr.Header
298 t.StatusCode = rr.StatusCode
299 t.ProtoMajor = rr.ProtoMajor
300 t.ProtoMinor = rr.ProtoMinor
301 t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header)
302 isResponse = true
303 if rr.Request != nil {
304 t.RequestMethod = rr.Request.Method
306 case *Request:
307 t.Header = rr.Header
308 t.ProtoMajor = rr.ProtoMajor
309 t.ProtoMinor = rr.ProtoMinor
310 // Transfer semantics for Requests are exactly like those for
311 // Responses with status code 200, responding to a GET method
312 t.StatusCode = 200
313 default:
314 panic("unexpected type")
317 // Default to HTTP/1.1
318 if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
319 t.ProtoMajor, t.ProtoMinor = 1, 1
322 // Transfer encoding, content length
323 t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header)
324 if err != nil {
325 return err
328 realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
329 if err != nil {
330 return err
332 if isResponse && t.RequestMethod == "HEAD" {
333 if n, err := parseContentLength(t.Header.get("Content-Length")); err != nil {
334 return err
335 } else {
336 t.ContentLength = n
338 } else {
339 t.ContentLength = realLength
342 // Trailer
343 t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
344 if err != nil {
345 return err
348 // If there is no Content-Length or chunked Transfer-Encoding on a *Response
349 // and the status is not 1xx, 204 or 304, then the body is unbounded.
350 // See RFC2616, section 4.4.
351 switch msg.(type) {
352 case *Response:
353 if realLength == -1 &&
354 !chunked(t.TransferEncoding) &&
355 bodyAllowedForStatus(t.StatusCode) {
356 // Unbounded body.
357 t.Close = true
361 // Prepare body reader. ContentLength < 0 means chunked encoding
362 // or close connection when finished, since multipart is not supported yet
363 switch {
364 case chunked(t.TransferEncoding):
365 if noBodyExpected(t.RequestMethod) {
366 t.Body = eofReader
367 } else {
368 t.Body = &body{src: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
370 case realLength == 0:
371 t.Body = eofReader
372 case realLength > 0:
373 t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
374 default:
375 // realLength < 0, i.e. "Content-Length" not mentioned in header
376 if t.Close {
377 // Close semantics (i.e. HTTP/1.0)
378 t.Body = &body{src: r, closing: t.Close}
379 } else {
380 // Persistent connection (i.e. HTTP/1.1)
381 t.Body = eofReader
385 // Unify output
386 switch rr := msg.(type) {
387 case *Request:
388 rr.Body = t.Body
389 rr.ContentLength = t.ContentLength
390 rr.TransferEncoding = t.TransferEncoding
391 rr.Close = t.Close
392 rr.Trailer = t.Trailer
393 case *Response:
394 rr.Body = t.Body
395 rr.ContentLength = t.ContentLength
396 rr.TransferEncoding = t.TransferEncoding
397 rr.Close = t.Close
398 rr.Trailer = t.Trailer
401 return nil
404 // Checks whether chunked is part of the encodings stack
405 func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
407 // Checks whether the encoding is explicitly "identity".
408 func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
410 // Sanitize transfer encoding
411 func fixTransferEncoding(requestMethod string, header Header) ([]string, error) {
412 raw, present := header["Transfer-Encoding"]
413 if !present {
414 return nil, nil
417 delete(header, "Transfer-Encoding")
419 encodings := strings.Split(raw[0], ",")
420 te := make([]string, 0, len(encodings))
421 // TODO: Even though we only support "identity" and "chunked"
422 // encodings, the loop below is designed with foresight. One
423 // invariant that must be maintained is that, if present,
424 // chunked encoding must always come first.
425 for _, encoding := range encodings {
426 encoding = strings.ToLower(strings.TrimSpace(encoding))
427 // "identity" encoding is not recorded
428 if encoding == "identity" {
429 break
431 if encoding != "chunked" {
432 return nil, &badStringError{"unsupported transfer encoding", encoding}
434 te = te[0 : len(te)+1]
435 te[len(te)-1] = encoding
437 if len(te) > 1 {
438 return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")}
440 if len(te) > 0 {
441 // Chunked encoding trumps Content-Length. See RFC 2616
442 // Section 4.4. Currently len(te) > 0 implies chunked
443 // encoding.
444 delete(header, "Content-Length")
445 return te, nil
448 return nil, nil
451 // Determine the expected body length, using RFC 2616 Section 4.4. This
452 // function is not a method, because ultimately it should be shared by
453 // ReadResponse and ReadRequest.
454 func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) {
456 // Logic based on response type or status
457 if noBodyExpected(requestMethod) {
458 return 0, nil
460 if status/100 == 1 {
461 return 0, nil
463 switch status {
464 case 204, 304:
465 return 0, nil
468 // Logic based on Transfer-Encoding
469 if chunked(te) {
470 return -1, nil
473 // Logic based on Content-Length
474 cl := strings.TrimSpace(header.get("Content-Length"))
475 if cl != "" {
476 n, err := parseContentLength(cl)
477 if err != nil {
478 return -1, err
480 return n, nil
481 } else {
482 header.Del("Content-Length")
485 if !isResponse && requestMethod == "GET" {
486 // RFC 2616 doesn't explicitly permit nor forbid an
487 // entity-body on a GET request so we permit one if
488 // declared, but we default to 0 here (not -1 below)
489 // if there's no mention of a body.
490 return 0, nil
493 // Body-EOF logic based on other methods (like closing, or chunked coding)
494 return -1, nil
497 // Determine whether to hang up after sending a request and body, or
498 // receiving a response and body
499 // 'header' is the request headers
500 func shouldClose(major, minor int, header Header) bool {
501 if major < 1 {
502 return true
503 } else if major == 1 && minor == 0 {
504 if !strings.Contains(strings.ToLower(header.get("Connection")), "keep-alive") {
505 return true
507 return false
508 } else {
509 // TODO: Should split on commas, toss surrounding white space,
510 // and check each field.
511 if strings.ToLower(header.get("Connection")) == "close" {
512 header.Del("Connection")
513 return true
516 return false
519 // Parse the trailer header
520 func fixTrailer(header Header, te []string) (Header, error) {
521 raw := header.get("Trailer")
522 if raw == "" {
523 return nil, nil
526 header.Del("Trailer")
527 trailer := make(Header)
528 keys := strings.Split(raw, ",")
529 for _, key := range keys {
530 key = CanonicalHeaderKey(strings.TrimSpace(key))
531 switch key {
532 case "Transfer-Encoding", "Trailer", "Content-Length":
533 return nil, &badStringError{"bad trailer key", key}
535 trailer[key] = nil
537 if len(trailer) == 0 {
538 return nil, nil
540 if !chunked(te) {
541 // Trailer and no chunking
542 return nil, ErrUnexpectedTrailer
544 return trailer, nil
547 // body turns a Reader into a ReadCloser.
548 // Close ensures that the body has been fully read
549 // and then reads the trailer if necessary.
550 type body struct {
551 src io.Reader
552 hdr interface{} // non-nil (Response or Request) value means read trailer
553 r *bufio.Reader // underlying wire-format reader for the trailer
554 closing bool // is the connection to be closed after reading body?
556 mu sync.Mutex // guards closed, and calls to Read and Close
557 closed bool
560 // ErrBodyReadAfterClose is returned when reading a Request or Response
561 // Body after the body has been closed. This typically happens when the body is
562 // read after an HTTP Handler calls WriteHeader or Write on its
563 // ResponseWriter.
564 var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
566 func (b *body) Read(p []byte) (n int, err error) {
567 b.mu.Lock()
568 defer b.mu.Unlock()
569 if b.closed {
570 return 0, ErrBodyReadAfterClose
572 return b.readLocked(p)
575 // Must hold b.mu.
576 func (b *body) readLocked(p []byte) (n int, err error) {
577 n, err = b.src.Read(p)
579 if err == io.EOF {
580 // Chunked case. Read the trailer.
581 if b.hdr != nil {
582 if e := b.readTrailer(); e != nil {
583 err = e
585 b.hdr = nil
586 } else {
587 // If the server declared the Content-Length, our body is a LimitedReader
588 // and we need to check whether this EOF arrived early.
589 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > 0 {
590 err = io.ErrUnexpectedEOF
595 // If we can return an EOF here along with the read data, do
596 // so. This is optional per the io.Reader contract, but doing
597 // so helps the HTTP transport code recycle its connection
598 // earlier (since it will see this EOF itself), even if the
599 // client doesn't do future reads or Close.
600 if err == nil && n > 0 {
601 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N == 0 {
602 err = io.EOF
606 return n, err
609 var (
610 singleCRLF = []byte("\r\n")
611 doubleCRLF = []byte("\r\n\r\n")
614 func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
615 for peekSize := 4; ; peekSize++ {
616 // This loop stops when Peek returns an error,
617 // which it does when r's buffer has been filled.
618 buf, err := r.Peek(peekSize)
619 if bytes.HasSuffix(buf, doubleCRLF) {
620 return true
622 if err != nil {
623 break
626 return false
629 var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
631 func (b *body) readTrailer() error {
632 // The common case, since nobody uses trailers.
633 buf, err := b.r.Peek(2)
634 if bytes.Equal(buf, singleCRLF) {
635 b.r.ReadByte()
636 b.r.ReadByte()
637 return nil
639 if len(buf) < 2 {
640 return errTrailerEOF
642 if err != nil {
643 return err
646 // Make sure there's a header terminator coming up, to prevent
647 // a DoS with an unbounded size Trailer. It's not easy to
648 // slip in a LimitReader here, as textproto.NewReader requires
649 // a concrete *bufio.Reader. Also, we can't get all the way
650 // back up to our conn's LimitedReader that *might* be backing
651 // this bufio.Reader. Instead, a hack: we iteratively Peek up
652 // to the bufio.Reader's max size, looking for a double CRLF.
653 // This limits the trailer to the underlying buffer size, typically 4kB.
654 if !seeUpcomingDoubleCRLF(b.r) {
655 return errors.New("http: suspiciously long trailer after chunked body")
658 hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
659 if err != nil {
660 if err == io.EOF {
661 return errTrailerEOF
663 return err
665 switch rr := b.hdr.(type) {
666 case *Request:
667 mergeSetHeader(&rr.Trailer, Header(hdr))
668 case *Response:
669 mergeSetHeader(&rr.Trailer, Header(hdr))
671 return nil
674 func mergeSetHeader(dst *Header, src Header) {
675 if *dst == nil {
676 *dst = src
677 return
679 for k, vv := range src {
680 (*dst)[k] = vv
684 func (b *body) Close() error {
685 b.mu.Lock()
686 defer b.mu.Unlock()
687 if b.closed {
688 return nil
690 var err error
691 switch {
692 case b.hdr == nil && b.closing:
693 // no trailer and closing the connection next.
694 // no point in reading to EOF.
695 default:
696 // Fully consume the body, which will also lead to us reading
697 // the trailer headers after the body, if present.
698 _, err = io.Copy(ioutil.Discard, bodyLocked{b})
700 b.closed = true
701 return err
704 // bodyLocked is a io.Reader reading from a *body when its mutex is
705 // already held.
706 type bodyLocked struct {
707 b *body
710 func (bl bodyLocked) Read(p []byte) (n int, err error) {
711 if bl.b.closed {
712 return 0, ErrBodyReadAfterClose
714 return bl.b.readLocked(p)
717 // parseContentLength trims whitespace from s and returns -1 if no value
718 // is set, or the value if it's >= 0.
719 func parseContentLength(cl string) (int64, error) {
720 cl = strings.TrimSpace(cl)
721 if cl == "" {
722 return -1, nil
724 n, err := strconv.ParseInt(cl, 10, 64)
725 if err != nil || n < 0 {
726 return 0, &badStringError{"bad Content-Length", cl}
728 return n, nil