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