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