~ubuntu-branches/ubuntu/trusty/golang/trusty

« back to all changes in this revision

Viewing changes to src/pkg/net/http/transfer.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
87
87
        // Sanitize Body,ContentLength,TransferEncoding
88
88
        if t.ResponseToHEAD {
89
89
                t.Body = nil
90
 
                t.TransferEncoding = nil
91
 
                // ContentLength is expected to hold Content-Length
92
 
                if t.ContentLength < 0 {
93
 
                        return nil, ErrMissingContentLength
 
90
                if chunked(t.TransferEncoding) {
 
91
                        t.ContentLength = -1
94
92
                }
95
93
        } else {
96
94
                if !atLeastHTTP11 || t.Body == nil {
122
120
        if t.ContentLength > 0 {
123
121
                return true
124
122
        }
125
 
        if t.ResponseToHEAD {
126
 
                return true
127
 
        }
128
123
        // Many servers expect a Content-Length for these methods
129
124
        if t.Method == "POST" || t.Method == "PUT" {
130
125
                return true
199
194
                        ncopy, err = io.Copy(w, t.Body)
200
195
                } else {
201
196
                        ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
202
 
                        nextra, err := io.Copy(ioutil.Discard, t.Body)
203
197
                        if err != nil {
204
198
                                return err
205
199
                        }
 
200
                        var nextra int64
 
201
                        nextra, err = io.Copy(ioutil.Discard, t.Body)
206
202
                        ncopy += nextra
207
203
                }
208
204
                if err != nil {
213
209
                }
214
210
        }
215
211
 
216
 
        if t.ContentLength != -1 && t.ContentLength != ncopy {
 
212
        if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
217
213
                return fmt.Errorf("http: Request.ContentLength=%d with Body length %d",
218
214
                        t.ContentLength, ncopy)
219
215
        }
294
290
                return err
295
291
        }
296
292
 
297
 
        t.ContentLength, err = fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
 
293
        realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
298
294
        if err != nil {
299
295
                return err
300
296
        }
 
297
        if isResponse && t.RequestMethod == "HEAD" {
 
298
                if n, err := parseContentLength(t.Header.get("Content-Length")); err != nil {
 
299
                        return err
 
300
                } else {
 
301
                        t.ContentLength = n
 
302
                }
 
303
        } else {
 
304
                t.ContentLength = realLength
 
305
        }
301
306
 
302
307
        // Trailer
303
308
        t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
310
315
        // See RFC2616, section 4.4.
311
316
        switch msg.(type) {
312
317
        case *Response:
313
 
                if t.ContentLength == -1 &&
 
318
                if realLength == -1 &&
314
319
                        !chunked(t.TransferEncoding) &&
315
320
                        bodyAllowedForStatus(t.StatusCode) {
316
321
                        // Unbounded body.
322
327
        // or close connection when finished, since multipart is not supported yet
323
328
        switch {
324
329
        case chunked(t.TransferEncoding):
325
 
                t.Body = &body{Reader: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
326
 
        case t.ContentLength >= 0:
327
 
                // TODO: limit the Content-Length. This is an easy DoS vector.
328
 
                t.Body = &body{Reader: io.LimitReader(r, t.ContentLength), closing: t.Close}
 
330
                if noBodyExpected(t.RequestMethod) {
 
331
                        t.Body = &body{Reader: eofReader, closing: t.Close}
 
332
                } else {
 
333
                        t.Body = &body{Reader: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
 
334
                }
 
335
        case realLength == 0:
 
336
                t.Body = &body{Reader: eofReader, closing: t.Close}
 
337
        case realLength > 0:
 
338
                t.Body = &body{Reader: io.LimitReader(r, realLength), closing: t.Close}
329
339
        default:
330
 
                // t.ContentLength < 0, i.e. "Content-Length" not mentioned in header
 
340
                // realLength < 0, i.e. "Content-Length" not mentioned in header
331
341
                if t.Close {
332
342
                        // Close semantics (i.e. HTTP/1.0)
333
343
                        t.Body = &body{Reader: r, closing: t.Close}
334
344
                } else {
335
345
                        // Persistent connection (i.e. HTTP/1.1)
336
 
                        t.Body = &body{Reader: io.LimitReader(r, 0), closing: t.Close}
 
346
                        t.Body = &body{Reader: eofReader, closing: t.Close}
337
347
                }
338
348
        }
339
349
 
371
381
 
372
382
        delete(header, "Transfer-Encoding")
373
383
 
374
 
        // Head responses have no bodies, so the transfer encoding
375
 
        // should be ignored.
376
 
        if requestMethod == "HEAD" {
377
 
                return nil, nil
378
 
        }
379
 
 
380
384
        encodings := strings.Split(raw[0], ",")
381
385
        te := make([]string, 0, len(encodings))
382
386
        // TODO: Even though we only support "identity" and "chunked"
432
436
        }
433
437
 
434
438
        // Logic based on Content-Length
435
 
        cl := strings.TrimSpace(header.Get("Content-Length"))
 
439
        cl := strings.TrimSpace(header.get("Content-Length"))
436
440
        if cl != "" {
437
 
                n, err := strconv.ParseInt(cl, 10, 64)
438
 
                if err != nil || n < 0 {
439
 
                        return -1, &badStringError{"bad Content-Length", cl}
 
441
                n, err := parseContentLength(cl)
 
442
                if err != nil {
 
443
                        return -1, err
440
444
                }
441
445
                return n, nil
442
446
        } else {
451
455
                return 0, nil
452
456
        }
453
457
 
454
 
        // Logic based on media type. The purpose of the following code is just
455
 
        // to detect whether the unsupported "multipart/byteranges" is being
456
 
        // used. A proper Content-Type parser is needed in the future.
457
 
        if strings.Contains(strings.ToLower(header.Get("Content-Type")), "multipart/byteranges") {
458
 
                return -1, ErrNotSupported
459
 
        }
460
 
 
461
458
        // Body-EOF logic based on other methods (like closing, or chunked coding)
462
459
        return -1, nil
463
460
}
469
466
        if major < 1 {
470
467
                return true
471
468
        } else if major == 1 && minor == 0 {
472
 
                if !strings.Contains(strings.ToLower(header.Get("Connection")), "keep-alive") {
 
469
                if !strings.Contains(strings.ToLower(header.get("Connection")), "keep-alive") {
473
470
                        return true
474
471
                }
475
472
                return false
476
473
        } else {
477
474
                // TODO: Should split on commas, toss surrounding white space,
478
475
                // and check each field.
479
 
                if strings.ToLower(header.Get("Connection")) == "close" {
 
476
                if strings.ToLower(header.get("Connection")) == "close" {
480
477
                        header.Del("Connection")
481
478
                        return true
482
479
                }
486
483
 
487
484
// Parse the trailer header
488
485
func fixTrailer(header Header, te []string) (Header, error) {
489
 
        raw := header.Get("Trailer")
 
486
        raw := header.get("Trailer")
490
487
        if raw == "" {
491
488
                return nil, nil
492
489
        }
525
522
        res *response // response writer for server requests, else nil
526
523
}
527
524
 
528
 
// ErrBodyReadAfterClose is returned when reading a Request Body after
529
 
// the body has been closed. This typically happens when the body is
 
525
// ErrBodyReadAfterClose is returned when reading a Request or Response
 
526
// Body after the body has been closed. This typically happens when the body is
530
527
// read after an HTTP Handler calls WriteHeader or Write on its
531
528
// ResponseWriter.
532
 
var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed request Body")
 
529
var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
533
530
 
534
531
func (b *body) Read(p []byte) (n int, err error) {
535
532
        if b.closed {
567
564
        return false
568
565
}
569
566
 
 
567
var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
 
568
 
570
569
func (b *body) readTrailer() error {
571
570
        // The common case, since nobody uses trailers.
572
 
        buf, _ := b.r.Peek(2)
 
571
        buf, err := b.r.Peek(2)
573
572
        if bytes.Equal(buf, singleCRLF) {
574
573
                b.r.ReadByte()
575
574
                b.r.ReadByte()
576
575
                return nil
577
576
        }
 
577
        if len(buf) < 2 {
 
578
                return errTrailerEOF
 
579
        }
 
580
        if err != nil {
 
581
                return err
 
582
        }
578
583
 
579
584
        // Make sure there's a header terminator coming up, to prevent
580
585
        // a DoS with an unbounded size Trailer.  It's not easy to
590
595
 
591
596
        hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
592
597
        if err != nil {
 
598
                if err == io.EOF {
 
599
                        return errTrailerEOF
 
600
                }
593
601
                return err
594
602
        }
595
603
        switch rr := b.hdr.(type) {
605
613
        if b.closed {
606
614
                return nil
607
615
        }
608
 
        defer func() {
609
 
                b.closed = true
610
 
        }()
611
 
        if b.hdr == nil && b.closing {
 
616
        var err error
 
617
        switch {
 
618
        case b.hdr == nil && b.closing:
612
619
                // no trailer and closing the connection next.
613
620
                // no point in reading to EOF.
614
 
                return nil
615
 
        }
616
 
 
617
 
        // In a server request, don't continue reading from the client
618
 
        // if we've already hit the maximum body size set by the
619
 
        // handler. If this is set, that also means the TCP connection
620
 
        // is about to be closed, so getting to the next HTTP request
621
 
        // in the stream is not necessary.
622
 
        if b.res != nil && b.res.requestBodyLimitHit {
623
 
                return nil
624
 
        }
625
 
 
626
 
        // Fully consume the body, which will also lead to us reading
627
 
        // the trailer headers after the body, if present.
628
 
        if _, err := io.Copy(ioutil.Discard, b); err != nil {
629
 
                return err
630
 
        }
631
 
        return nil
 
621
        case b.res != nil && b.res.requestBodyLimitHit:
 
622
                // In a server request, don't continue reading from the client
 
623
                // if we've already hit the maximum body size set by the
 
624
                // handler. If this is set, that also means the TCP connection
 
625
                // is about to be closed, so getting to the next HTTP request
 
626
                // in the stream is not necessary.
 
627
        case b.Reader == eofReader:
 
628
                // Nothing to read. No need to io.Copy from it.
 
629
        default:
 
630
                // Fully consume the body, which will also lead to us reading
 
631
                // the trailer headers after the body, if present.
 
632
                _, err = io.Copy(ioutil.Discard, b)
 
633
        }
 
634
        b.closed = true
 
635
        return err
 
636
}
 
637
 
 
638
// parseContentLength trims whitespace from s and returns -1 if no value
 
639
// is set, or the value if it's >= 0.
 
640
func parseContentLength(cl string) (int64, error) {
 
641
        cl = strings.TrimSpace(cl)
 
642
        if cl == "" {
 
643
                return -1, nil
 
644
        }
 
645
        n, err := strconv.ParseInt(cl, 10, 64)
 
646
        if err != nil || n < 0 {
 
647
                return 0, &badStringError{"bad Content-Length", cl}
 
648
        }
 
649
        return n, nil
 
650
 
632
651
}