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