Source file
src/net/http/transfer.go
1
2
3
4
5 package http
6
7 import (
8 "bufio"
9 "bytes"
10 "errors"
11 "fmt"
12 "io"
13 "net/http/httptrace"
14 "net/http/internal"
15 "net/http/internal/ascii"
16 "net/textproto"
17 "reflect"
18 "sort"
19 "strconv"
20 "strings"
21 "sync"
22 "time"
23
24 "golang.org/x/net/http/httpguts"
25 )
26
27
28
29 var ErrLineTooLong = internal.ErrLineTooLong
30
31 type errorReader struct {
32 err error
33 }
34
35 func (r errorReader) Read(p []byte) (n int, err error) {
36 return 0, r.err
37 }
38
39 type byteReader struct {
40 b byte
41 done bool
42 }
43
44 func (br *byteReader) Read(p []byte) (n int, err error) {
45 if br.done {
46 return 0, io.EOF
47 }
48 if len(p) == 0 {
49 return 0, nil
50 }
51 br.done = true
52 p[0] = br.b
53 return 1, io.EOF
54 }
55
56
57
58
59 type transferWriter struct {
60 Method string
61 Body io.Reader
62 BodyCloser io.Closer
63 ResponseToHEAD bool
64 ContentLength int64
65 Close bool
66 TransferEncoding []string
67 Header Header
68 Trailer Header
69 IsResponse bool
70 bodyReadError error
71
72 FlushHeaders bool
73 ByteReadCh chan readResult
74 }
75
76 func newTransferWriter(r interface{}) (t *transferWriter, err error) {
77 t = &transferWriter{}
78
79
80 atLeastHTTP11 := false
81 switch rr := r.(type) {
82 case *Request:
83 if rr.ContentLength != 0 && rr.Body == nil {
84 return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
85 }
86 t.Method = valueOrDefault(rr.Method, "GET")
87 t.Close = rr.Close
88 t.TransferEncoding = rr.TransferEncoding
89 t.Header = rr.Header
90 t.Trailer = rr.Trailer
91 t.Body = rr.Body
92 t.BodyCloser = rr.Body
93 t.ContentLength = rr.outgoingLength()
94 if t.ContentLength < 0 && len(t.TransferEncoding) == 0 && t.shouldSendChunkedRequestBody() {
95 t.TransferEncoding = []string{"chunked"}
96 }
97
98
99
100
101
102
103
104 if t.ContentLength != 0 && !isKnownInMemoryReader(t.Body) {
105 t.FlushHeaders = true
106 }
107
108 atLeastHTTP11 = true
109 case *Response:
110 t.IsResponse = true
111 if rr.Request != nil {
112 t.Method = rr.Request.Method
113 }
114 t.Body = rr.Body
115 t.BodyCloser = rr.Body
116 t.ContentLength = rr.ContentLength
117 t.Close = rr.Close
118 t.TransferEncoding = rr.TransferEncoding
119 t.Header = rr.Header
120 t.Trailer = rr.Trailer
121 atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
122 t.ResponseToHEAD = noResponseBodyExpected(t.Method)
123 }
124
125
126 if t.ResponseToHEAD {
127 t.Body = nil
128 if chunked(t.TransferEncoding) {
129 t.ContentLength = -1
130 }
131 } else {
132 if !atLeastHTTP11 || t.Body == nil {
133 t.TransferEncoding = nil
134 }
135 if chunked(t.TransferEncoding) {
136 t.ContentLength = -1
137 } else if t.Body == nil {
138 t.ContentLength = 0
139 }
140 }
141
142
143 if !chunked(t.TransferEncoding) {
144 t.Trailer = nil
145 }
146
147 return t, nil
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 func (t *transferWriter) shouldSendChunkedRequestBody() bool {
169
170
171 if t.ContentLength >= 0 || t.Body == nil {
172 return false
173 }
174 if t.Method == "CONNECT" {
175 return false
176 }
177 if requestMethodUsuallyLacksBody(t.Method) {
178
179
180
181 t.probeRequestBody()
182 return t.Body != nil
183 }
184
185
186
187
188 return true
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205 func (t *transferWriter) probeRequestBody() {
206 t.ByteReadCh = make(chan readResult, 1)
207 go func(body io.Reader) {
208 var buf [1]byte
209 var rres readResult
210 rres.n, rres.err = body.Read(buf[:])
211 if rres.n == 1 {
212 rres.b = buf[0]
213 }
214 t.ByteReadCh <- rres
215 }(t.Body)
216 timer := time.NewTimer(200 * time.Millisecond)
217 select {
218 case rres := <-t.ByteReadCh:
219 timer.Stop()
220 if rres.n == 0 && rres.err == io.EOF {
221
222 t.Body = nil
223 t.ContentLength = 0
224 } else if rres.n == 1 {
225 if rres.err != nil {
226 t.Body = io.MultiReader(&byteReader{b: rres.b}, errorReader{rres.err})
227 } else {
228 t.Body = io.MultiReader(&byteReader{b: rres.b}, t.Body)
229 }
230 } else if rres.err != nil {
231 t.Body = errorReader{rres.err}
232 }
233 case <-timer.C:
234
235
236
237
238 t.Body = io.MultiReader(finishAsyncByteRead{t}, t.Body)
239
240
241
242 t.FlushHeaders = true
243 }
244 }
245
246 func noResponseBodyExpected(requestMethod string) bool {
247 return requestMethod == "HEAD"
248 }
249
250 func (t *transferWriter) shouldSendContentLength() bool {
251 if chunked(t.TransferEncoding) {
252 return false
253 }
254 if t.ContentLength > 0 {
255 return true
256 }
257 if t.ContentLength < 0 {
258 return false
259 }
260
261 if t.Method == "POST" || t.Method == "PUT" || t.Method == "PATCH" {
262 return true
263 }
264 if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
265 if t.Method == "GET" || t.Method == "HEAD" {
266 return false
267 }
268 return true
269 }
270
271 return false
272 }
273
274 func (t *transferWriter) writeHeader(w io.Writer, trace *httptrace.ClientTrace) error {
275 if t.Close && !hasToken(t.Header.get("Connection"), "close") {
276 if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
277 return err
278 }
279 if trace != nil && trace.WroteHeaderField != nil {
280 trace.WroteHeaderField("Connection", []string{"close"})
281 }
282 }
283
284
285
286
287 if t.shouldSendContentLength() {
288 if _, err := io.WriteString(w, "Content-Length: "); err != nil {
289 return err
290 }
291 if _, err := io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n"); err != nil {
292 return err
293 }
294 if trace != nil && trace.WroteHeaderField != nil {
295 trace.WroteHeaderField("Content-Length", []string{strconv.FormatInt(t.ContentLength, 10)})
296 }
297 } else if chunked(t.TransferEncoding) {
298 if _, err := io.WriteString(w, "Transfer-Encoding: chunked\r\n"); err != nil {
299 return err
300 }
301 if trace != nil && trace.WroteHeaderField != nil {
302 trace.WroteHeaderField("Transfer-Encoding", []string{"chunked"})
303 }
304 }
305
306
307 if t.Trailer != nil {
308 keys := make([]string, 0, len(t.Trailer))
309 for k := range t.Trailer {
310 k = CanonicalHeaderKey(k)
311 switch k {
312 case "Transfer-Encoding", "Trailer", "Content-Length":
313 return badStringError("invalid Trailer key", k)
314 }
315 keys = append(keys, k)
316 }
317 if len(keys) > 0 {
318 sort.Strings(keys)
319
320
321 if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
322 return err
323 }
324 if trace != nil && trace.WroteHeaderField != nil {
325 trace.WroteHeaderField("Trailer", keys)
326 }
327 }
328 }
329
330 return nil
331 }
332
333
334 func (t *transferWriter) writeBody(w io.Writer) (err error) {
335 var ncopy int64
336 closed := false
337 defer func() {
338 if closed || t.BodyCloser == nil {
339 return
340 }
341 if closeErr := t.BodyCloser.Close(); closeErr != nil && err == nil {
342 err = closeErr
343 }
344 }()
345
346
347
348
349
350 if t.Body != nil {
351 var body = t.unwrapBody()
352 if chunked(t.TransferEncoding) {
353 if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
354 w = &internal.FlushAfterChunkWriter{Writer: bw}
355 }
356 cw := internal.NewChunkedWriter(w)
357 _, err = t.doBodyCopy(cw, body)
358 if err == nil {
359 err = cw.Close()
360 }
361 } else if t.ContentLength == -1 {
362 dst := w
363 if t.Method == "CONNECT" {
364 dst = bufioFlushWriter{dst}
365 }
366 ncopy, err = t.doBodyCopy(dst, body)
367 } else {
368 ncopy, err = t.doBodyCopy(w, io.LimitReader(body, t.ContentLength))
369 if err != nil {
370 return err
371 }
372 var nextra int64
373 nextra, err = t.doBodyCopy(io.Discard, body)
374 ncopy += nextra
375 }
376 if err != nil {
377 return err
378 }
379 }
380 if t.BodyCloser != nil {
381 closed = true
382 if err := t.BodyCloser.Close(); err != nil {
383 return err
384 }
385 }
386
387 if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
388 return fmt.Errorf("http: ContentLength=%d with Body length %d",
389 t.ContentLength, ncopy)
390 }
391
392 if chunked(t.TransferEncoding) {
393
394 if t.Trailer != nil {
395 if err := t.Trailer.Write(w); err != nil {
396 return err
397 }
398 }
399
400 _, err = io.WriteString(w, "\r\n")
401 }
402 return err
403 }
404
405
406
407
408
409 func (t *transferWriter) doBodyCopy(dst io.Writer, src io.Reader) (n int64, err error) {
410 n, err = io.Copy(dst, src)
411 if err != nil && err != io.EOF {
412 t.bodyReadError = err
413 }
414 return
415 }
416
417
418
419
420
421
422 func (t *transferWriter) unwrapBody() io.Reader {
423 if reflect.TypeOf(t.Body) == nopCloserType {
424 return reflect.ValueOf(t.Body).Field(0).Interface().(io.Reader)
425 }
426 if r, ok := t.Body.(*readTrackingBody); ok {
427 r.didRead = true
428 return r.ReadCloser
429 }
430 return t.Body
431 }
432
433 type transferReader struct {
434
435 Header Header
436 StatusCode int
437 RequestMethod string
438 ProtoMajor int
439 ProtoMinor int
440
441 Body io.ReadCloser
442 ContentLength int64
443 Chunked bool
444 Close bool
445 Trailer Header
446 }
447
448 func (t *transferReader) protoAtLeast(m, n int) bool {
449 return t.ProtoMajor > m || (t.ProtoMajor == m && t.ProtoMinor >= n)
450 }
451
452
453
454 func bodyAllowedForStatus(status int) bool {
455 switch {
456 case status >= 100 && status <= 199:
457 return false
458 case status == 204:
459 return false
460 case status == 304:
461 return false
462 }
463 return true
464 }
465
466 var (
467 suppressedHeaders304 = []string{"Content-Type", "Content-Length", "Transfer-Encoding"}
468 suppressedHeadersNoBody = []string{"Content-Length", "Transfer-Encoding"}
469 )
470
471 func suppressedHeaders(status int) []string {
472 switch {
473 case status == 304:
474
475 return suppressedHeaders304
476 case !bodyAllowedForStatus(status):
477 return suppressedHeadersNoBody
478 }
479 return nil
480 }
481
482
483 func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
484 t := &transferReader{RequestMethod: "GET"}
485
486
487 isResponse := false
488 switch rr := msg.(type) {
489 case *Response:
490 t.Header = rr.Header
491 t.StatusCode = rr.StatusCode
492 t.ProtoMajor = rr.ProtoMajor
493 t.ProtoMinor = rr.ProtoMinor
494 t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header, true)
495 isResponse = true
496 if rr.Request != nil {
497 t.RequestMethod = rr.Request.Method
498 }
499 case *Request:
500 t.Header = rr.Header
501 t.RequestMethod = rr.Method
502 t.ProtoMajor = rr.ProtoMajor
503 t.ProtoMinor = rr.ProtoMinor
504
505
506 t.StatusCode = 200
507 t.Close = rr.Close
508 default:
509 panic("unexpected type")
510 }
511
512
513 if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
514 t.ProtoMajor, t.ProtoMinor = 1, 1
515 }
516
517
518 if err := t.parseTransferEncoding(); err != nil {
519 return err
520 }
521
522 realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.Chunked)
523 if err != nil {
524 return err
525 }
526 if isResponse && t.RequestMethod == "HEAD" {
527 if n, err := parseContentLength(t.Header.get("Content-Length")); err != nil {
528 return err
529 } else {
530 t.ContentLength = n
531 }
532 } else {
533 t.ContentLength = realLength
534 }
535
536
537 t.Trailer, err = fixTrailer(t.Header, t.Chunked)
538 if err != nil {
539 return err
540 }
541
542
543
544
545 switch msg.(type) {
546 case *Response:
547 if realLength == -1 && !t.Chunked && bodyAllowedForStatus(t.StatusCode) {
548
549 t.Close = true
550 }
551 }
552
553
554
555 switch {
556 case t.Chunked:
557 if noResponseBodyExpected(t.RequestMethod) || !bodyAllowedForStatus(t.StatusCode) {
558 t.Body = NoBody
559 } else {
560 t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
561 }
562 case realLength == 0:
563 t.Body = NoBody
564 case realLength > 0:
565 t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
566 default:
567
568 if t.Close {
569
570 t.Body = &body{src: r, closing: t.Close}
571 } else {
572
573 t.Body = NoBody
574 }
575 }
576
577
578 switch rr := msg.(type) {
579 case *Request:
580 rr.Body = t.Body
581 rr.ContentLength = t.ContentLength
582 if t.Chunked {
583 rr.TransferEncoding = []string{"chunked"}
584 }
585 rr.Close = t.Close
586 rr.Trailer = t.Trailer
587 case *Response:
588 rr.Body = t.Body
589 rr.ContentLength = t.ContentLength
590 if t.Chunked {
591 rr.TransferEncoding = []string{"chunked"}
592 }
593 rr.Close = t.Close
594 rr.Trailer = t.Trailer
595 }
596
597 return nil
598 }
599
600
601 func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
602
603
604 func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
605
606
607 type unsupportedTEError struct {
608 err string
609 }
610
611 func (uste *unsupportedTEError) Error() string {
612 return uste.err
613 }
614
615
616
617 func isUnsupportedTEError(err error) bool {
618 _, ok := err.(*unsupportedTEError)
619 return ok
620 }
621
622
623 func (t *transferReader) parseTransferEncoding() error {
624 raw, present := t.Header["Transfer-Encoding"]
625 if !present {
626 return nil
627 }
628 delete(t.Header, "Transfer-Encoding")
629
630
631 if !t.protoAtLeast(1, 1) {
632 return nil
633 }
634
635
636
637
638
639 if len(raw) != 1 {
640 return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", raw)}
641 }
642 if !ascii.EqualFold(raw[0], "chunked") {
643 return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", raw[0])}
644 }
645
646
647
648
649
650
651
652
653
654
655
656
657 delete(t.Header, "Content-Length")
658
659 t.Chunked = true
660 return nil
661 }
662
663
664
665
666 func fixLength(isResponse bool, status int, requestMethod string, header Header, chunked bool) (int64, error) {
667 isRequest := !isResponse
668 contentLens := header["Content-Length"]
669
670
671 if len(contentLens) > 1 {
672
673
674
675
676 first := textproto.TrimString(contentLens[0])
677 for _, ct := range contentLens[1:] {
678 if first != textproto.TrimString(ct) {
679 return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", contentLens)
680 }
681 }
682
683
684 header.Del("Content-Length")
685 header.Add("Content-Length", first)
686
687 contentLens = header["Content-Length"]
688 }
689
690
691 if noResponseBodyExpected(requestMethod) {
692
693
694
695
696 if isRequest && len(contentLens) > 0 && !(len(contentLens) == 1 && contentLens[0] == "0") {
697 return 0, fmt.Errorf("http: method cannot contain a Content-Length; got %q", contentLens)
698 }
699 return 0, nil
700 }
701 if status/100 == 1 {
702 return 0, nil
703 }
704 switch status {
705 case 204, 304:
706 return 0, nil
707 }
708
709
710 if chunked {
711 return -1, nil
712 }
713
714
715 var cl string
716 if len(contentLens) == 1 {
717 cl = textproto.TrimString(contentLens[0])
718 }
719 if cl != "" {
720 n, err := parseContentLength(cl)
721 if err != nil {
722 return -1, err
723 }
724 return n, nil
725 }
726 header.Del("Content-Length")
727
728 if isRequest {
729
730
731
732
733
734
735
736 return 0, nil
737 }
738
739
740 return -1, nil
741 }
742
743
744
745
746 func shouldClose(major, minor int, header Header, removeCloseHeader bool) bool {
747 if major < 1 {
748 return true
749 }
750
751 conv := header["Connection"]
752 hasClose := httpguts.HeaderValuesContainsToken(conv, "close")
753 if major == 1 && minor == 0 {
754 return hasClose || !httpguts.HeaderValuesContainsToken(conv, "keep-alive")
755 }
756
757 if hasClose && removeCloseHeader {
758 header.Del("Connection")
759 }
760
761 return hasClose
762 }
763
764
765 func fixTrailer(header Header, chunked bool) (Header, error) {
766 vv, ok := header["Trailer"]
767 if !ok {
768 return nil, nil
769 }
770 if !chunked {
771
772
773
774
775
776
777
778 return nil, nil
779 }
780 header.Del("Trailer")
781
782 trailer := make(Header)
783 var err error
784 for _, v := range vv {
785 foreachHeaderElement(v, func(key string) {
786 key = CanonicalHeaderKey(key)
787 switch key {
788 case "Transfer-Encoding", "Trailer", "Content-Length":
789 if err == nil {
790 err = badStringError("bad trailer key", key)
791 return
792 }
793 }
794 trailer[key] = nil
795 })
796 }
797 if err != nil {
798 return nil, err
799 }
800 if len(trailer) == 0 {
801 return nil, nil
802 }
803 return trailer, nil
804 }
805
806
807
808
809 type body struct {
810 src io.Reader
811 hdr interface{}
812 r *bufio.Reader
813 closing bool
814 doEarlyClose bool
815
816 mu sync.Mutex
817 sawEOF bool
818 closed bool
819 earlyClose bool
820 onHitEOF func()
821 }
822
823
824
825
826
827 var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
828
829 func (b *body) Read(p []byte) (n int, err error) {
830 b.mu.Lock()
831 defer b.mu.Unlock()
832 if b.closed {
833 return 0, ErrBodyReadAfterClose
834 }
835 return b.readLocked(p)
836 }
837
838
839 func (b *body) readLocked(p []byte) (n int, err error) {
840 if b.sawEOF {
841 return 0, io.EOF
842 }
843 n, err = b.src.Read(p)
844
845 if err == io.EOF {
846 b.sawEOF = true
847
848 if b.hdr != nil {
849 if e := b.readTrailer(); e != nil {
850 err = e
851
852
853
854
855 b.sawEOF = false
856 b.closed = true
857 }
858 b.hdr = nil
859 } else {
860
861
862 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > 0 {
863 err = io.ErrUnexpectedEOF
864 }
865 }
866 }
867
868
869
870
871
872
873 if err == nil && n > 0 {
874 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N == 0 {
875 err = io.EOF
876 b.sawEOF = true
877 }
878 }
879
880 if b.sawEOF && b.onHitEOF != nil {
881 b.onHitEOF()
882 }
883
884 return n, err
885 }
886
887 var (
888 singleCRLF = []byte("\r\n")
889 doubleCRLF = []byte("\r\n\r\n")
890 )
891
892 func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
893 for peekSize := 4; ; peekSize++ {
894
895
896 buf, err := r.Peek(peekSize)
897 if bytes.HasSuffix(buf, doubleCRLF) {
898 return true
899 }
900 if err != nil {
901 break
902 }
903 }
904 return false
905 }
906
907 var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
908
909 func (b *body) readTrailer() error {
910
911 buf, err := b.r.Peek(2)
912 if bytes.Equal(buf, singleCRLF) {
913 b.r.Discard(2)
914 return nil
915 }
916 if len(buf) < 2 {
917 return errTrailerEOF
918 }
919 if err != nil {
920 return err
921 }
922
923
924
925
926
927
928
929
930
931 if !seeUpcomingDoubleCRLF(b.r) {
932 return errors.New("http: suspiciously long trailer after chunked body")
933 }
934
935 hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
936 if err != nil {
937 if err == io.EOF {
938 return errTrailerEOF
939 }
940 return err
941 }
942 switch rr := b.hdr.(type) {
943 case *Request:
944 mergeSetHeader(&rr.Trailer, Header(hdr))
945 case *Response:
946 mergeSetHeader(&rr.Trailer, Header(hdr))
947 }
948 return nil
949 }
950
951 func mergeSetHeader(dst *Header, src Header) {
952 if *dst == nil {
953 *dst = src
954 return
955 }
956 for k, vv := range src {
957 (*dst)[k] = vv
958 }
959 }
960
961
962
963
964 func (b *body) unreadDataSizeLocked() int64 {
965 if lr, ok := b.src.(*io.LimitedReader); ok {
966 return lr.N
967 }
968 return -1
969 }
970
971 func (b *body) Close() error {
972 b.mu.Lock()
973 defer b.mu.Unlock()
974 if b.closed {
975 return nil
976 }
977 var err error
978 switch {
979 case b.sawEOF:
980
981 case b.hdr == nil && b.closing:
982
983
984 case b.doEarlyClose:
985
986
987 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > maxPostHandlerReadBytes {
988
989
990 b.earlyClose = true
991 } else {
992 var n int64
993
994
995 n, err = io.CopyN(io.Discard, bodyLocked{b}, maxPostHandlerReadBytes)
996 if err == io.EOF {
997 err = nil
998 }
999 if n == maxPostHandlerReadBytes {
1000 b.earlyClose = true
1001 }
1002 }
1003 default:
1004
1005
1006 _, err = io.Copy(io.Discard, bodyLocked{b})
1007 }
1008 b.closed = true
1009 return err
1010 }
1011
1012 func (b *body) didEarlyClose() bool {
1013 b.mu.Lock()
1014 defer b.mu.Unlock()
1015 return b.earlyClose
1016 }
1017
1018
1019
1020 func (b *body) bodyRemains() bool {
1021 b.mu.Lock()
1022 defer b.mu.Unlock()
1023 return !b.sawEOF
1024 }
1025
1026 func (b *body) registerOnHitEOF(fn func()) {
1027 b.mu.Lock()
1028 defer b.mu.Unlock()
1029 b.onHitEOF = fn
1030 }
1031
1032
1033
1034 type bodyLocked struct {
1035 b *body
1036 }
1037
1038 func (bl bodyLocked) Read(p []byte) (n int, err error) {
1039 if bl.b.closed {
1040 return 0, ErrBodyReadAfterClose
1041 }
1042 return bl.b.readLocked(p)
1043 }
1044
1045
1046
1047 func parseContentLength(cl string) (int64, error) {
1048 cl = textproto.TrimString(cl)
1049 if cl == "" {
1050 return -1, nil
1051 }
1052 n, err := strconv.ParseUint(cl, 10, 63)
1053 if err != nil {
1054 return 0, badStringError("bad Content-Length", cl)
1055 }
1056 return int64(n), nil
1057
1058 }
1059
1060
1061
1062 type finishAsyncByteRead struct {
1063 tw *transferWriter
1064 }
1065
1066 func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) {
1067 if len(p) == 0 {
1068 return
1069 }
1070 rres := <-fr.tw.ByteReadCh
1071 n, err = rres.n, rres.err
1072 if n == 1 {
1073 p[0] = rres.b
1074 }
1075 return
1076 }
1077
1078 var nopCloserType = reflect.TypeOf(io.NopCloser(nil))
1079
1080
1081
1082
1083 func isKnownInMemoryReader(r io.Reader) bool {
1084 switch r.(type) {
1085 case *bytes.Reader, *bytes.Buffer, *strings.Reader:
1086 return true
1087 }
1088 if reflect.TypeOf(r) == nopCloserType {
1089 return isKnownInMemoryReader(reflect.ValueOf(r).Field(0).Interface().(io.Reader))
1090 }
1091 if r, ok := r.(*readTrackingBody); ok {
1092 return isKnownInMemoryReader(r.ReadCloser)
1093 }
1094 return false
1095 }
1096
1097
1098
1099 type bufioFlushWriter struct{ w io.Writer }
1100
1101 func (fw bufioFlushWriter) Write(p []byte) (n int, err error) {
1102 n, err = fw.w.Write(p)
1103 if bw, ok := fw.w.(*bufio.Writer); n > 0 && ok {
1104 ferr := bw.Flush()
1105 if ferr != nil && err == nil {
1106 err = ferr
1107 }
1108 }
1109 return
1110 }
1111
View as plain text