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 "slices"
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 slices.Sort(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 t.Chunked = true
654 return nil
655 }
656
657
658
659
660 func fixLength(isResponse bool, status int, requestMethod string, header Header, chunked bool) (n int64, err error) {
661 isRequest := !isResponse
662 contentLens := header["Content-Length"]
663
664
665 if len(contentLens) > 1 {
666
667
668
669
670 first := textproto.TrimString(contentLens[0])
671 for _, ct := range contentLens[1:] {
672 if first != textproto.TrimString(ct) {
673 return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", contentLens)
674 }
675 }
676
677
678 header.Del("Content-Length")
679 header.Add("Content-Length", first)
680
681 contentLens = header["Content-Length"]
682 }
683
684
685 if len(contentLens) > 0 {
686 n, err = parseContentLength(contentLens)
687 if err != nil {
688 return -1, err
689 }
690 }
691
692
693 if isResponse && noResponseBodyExpected(requestMethod) {
694 return 0, nil
695 }
696 if status/100 == 1 {
697 return 0, nil
698 }
699 switch status {
700 case 204, 304:
701 return 0, nil
702 }
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717 if chunked {
718 header.Del("Content-Length")
719 return -1, nil
720 }
721
722
723 if len(contentLens) > 0 {
724 return n, nil
725 }
726
727 header.Del("Content-Length")
728
729 if isRequest {
730
731
732
733
734
735
736
737 return 0, nil
738 }
739
740
741 return -1, nil
742 }
743
744
745
746
747 func shouldClose(major, minor int, header Header, removeCloseHeader bool) bool {
748 if major < 1 {
749 return true
750 }
751
752 conv := header["Connection"]
753 hasClose := httpguts.HeaderValuesContainsToken(conv, "close")
754 if major == 1 && minor == 0 {
755 return hasClose || !httpguts.HeaderValuesContainsToken(conv, "keep-alive")
756 }
757
758 if hasClose && removeCloseHeader {
759 header.Del("Connection")
760 }
761
762 return hasClose
763 }
764
765
766 func fixTrailer(header Header, chunked bool) (Header, error) {
767 vv, ok := header["Trailer"]
768 if !ok {
769 return nil, nil
770 }
771 if !chunked {
772
773
774
775
776
777
778
779 return nil, nil
780 }
781 header.Del("Trailer")
782
783 trailer := make(Header)
784 var err error
785 for _, v := range vv {
786 foreachHeaderElement(v, func(key string) {
787 key = CanonicalHeaderKey(key)
788 switch key {
789 case "Transfer-Encoding", "Trailer", "Content-Length":
790 if err == nil {
791 err = badStringError("bad trailer key", key)
792 return
793 }
794 }
795 trailer[key] = nil
796 })
797 }
798 if err != nil {
799 return nil, err
800 }
801 if len(trailer) == 0 {
802 return nil, nil
803 }
804 return trailer, nil
805 }
806
807
808
809
810 type body struct {
811 src io.Reader
812 hdr any
813 r *bufio.Reader
814 closing bool
815 doEarlyClose bool
816
817 mu sync.Mutex
818 sawEOF bool
819 closed bool
820 earlyClose bool
821 onHitEOF func()
822 }
823
824
825
826
827
828 var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
829
830 func (b *body) Read(p []byte) (n int, err error) {
831 b.mu.Lock()
832 defer b.mu.Unlock()
833 if b.closed {
834 return 0, ErrBodyReadAfterClose
835 }
836 return b.readLocked(p)
837 }
838
839
840 func (b *body) readLocked(p []byte) (n int, err error) {
841 if b.sawEOF {
842 return 0, io.EOF
843 }
844 n, err = b.src.Read(p)
845
846 if err == io.EOF {
847 b.sawEOF = true
848
849 if b.hdr != nil {
850 if e := b.readTrailer(); e != nil {
851 err = e
852
853
854
855
856 b.sawEOF = false
857 b.closed = true
858 }
859 b.hdr = nil
860 } else {
861
862
863 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > 0 {
864 err = io.ErrUnexpectedEOF
865 }
866 }
867 }
868
869
870
871
872
873
874 if err == nil && n > 0 {
875 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N == 0 {
876 err = io.EOF
877 b.sawEOF = true
878 }
879 }
880
881 if b.sawEOF && b.onHitEOF != nil {
882 b.onHitEOF()
883 }
884
885 return n, err
886 }
887
888 var (
889 singleCRLF = []byte("\r\n")
890 doubleCRLF = []byte("\r\n\r\n")
891 )
892
893 func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
894 for peekSize := 4; ; peekSize++ {
895
896
897 buf, err := r.Peek(peekSize)
898 if bytes.HasSuffix(buf, doubleCRLF) {
899 return true
900 }
901 if err != nil {
902 break
903 }
904 }
905 return false
906 }
907
908 var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
909
910 func (b *body) readTrailer() error {
911
912 buf, err := b.r.Peek(2)
913 if bytes.Equal(buf, singleCRLF) {
914 b.r.Discard(2)
915 return nil
916 }
917 if len(buf) < 2 {
918 return errTrailerEOF
919 }
920 if err != nil {
921 return err
922 }
923
924
925
926
927
928
929
930
931
932 if !seeUpcomingDoubleCRLF(b.r) {
933 return errors.New("http: suspiciously long trailer after chunked body")
934 }
935
936 hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
937 if err != nil {
938 if err == io.EOF {
939 return errTrailerEOF
940 }
941 return err
942 }
943 switch rr := b.hdr.(type) {
944 case *Request:
945 mergeSetHeader(&rr.Trailer, Header(hdr))
946 case *Response:
947 mergeSetHeader(&rr.Trailer, Header(hdr))
948 }
949 return nil
950 }
951
952 func mergeSetHeader(dst *Header, src Header) {
953 if *dst == nil {
954 *dst = src
955 return
956 }
957 for k, vv := range src {
958 (*dst)[k] = vv
959 }
960 }
961
962
963
964
965 func (b *body) unreadDataSizeLocked() int64 {
966 if lr, ok := b.src.(*io.LimitedReader); ok {
967 return lr.N
968 }
969 return -1
970 }
971
972 func (b *body) Close() error {
973 b.mu.Lock()
974 defer b.mu.Unlock()
975 if b.closed {
976 return nil
977 }
978 var err error
979 switch {
980 case b.sawEOF:
981
982 case b.hdr == nil && b.closing:
983
984
985 case b.doEarlyClose:
986
987
988 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > maxPostHandlerReadBytes {
989
990
991 b.earlyClose = true
992 } else {
993 var n int64
994
995
996 n, err = io.CopyN(io.Discard, bodyLocked{b}, maxPostHandlerReadBytes)
997 if err == io.EOF {
998 err = nil
999 }
1000 if n == maxPostHandlerReadBytes {
1001 b.earlyClose = true
1002 }
1003 }
1004 default:
1005
1006
1007 _, err = io.Copy(io.Discard, bodyLocked{b})
1008 }
1009 b.closed = true
1010 return err
1011 }
1012
1013 func (b *body) didEarlyClose() bool {
1014 b.mu.Lock()
1015 defer b.mu.Unlock()
1016 return b.earlyClose
1017 }
1018
1019
1020
1021 func (b *body) bodyRemains() bool {
1022 b.mu.Lock()
1023 defer b.mu.Unlock()
1024 return !b.sawEOF
1025 }
1026
1027 func (b *body) registerOnHitEOF(fn func()) {
1028 b.mu.Lock()
1029 defer b.mu.Unlock()
1030 b.onHitEOF = fn
1031 }
1032
1033
1034
1035 type bodyLocked struct {
1036 b *body
1037 }
1038
1039 func (bl bodyLocked) Read(p []byte) (n int, err error) {
1040 if bl.b.closed {
1041 return 0, ErrBodyReadAfterClose
1042 }
1043 return bl.b.readLocked(p)
1044 }
1045
1046 var httplaxcontentlength = godebug.New("httplaxcontentlength")
1047
1048
1049
1050
1051 func parseContentLength(clHeaders []string) (int64, error) {
1052 if len(clHeaders) == 0 {
1053 return -1, nil
1054 }
1055 cl := textproto.TrimString(clHeaders[0])
1056
1057
1058
1059 if cl == "" {
1060 if httplaxcontentlength.Value() == "1" {
1061 httplaxcontentlength.IncNonDefault()
1062 return -1, nil
1063 }
1064 return 0, badStringError("invalid empty Content-Length", cl)
1065 }
1066 n, err := strconv.ParseUint(cl, 10, 63)
1067 if err != nil {
1068 return 0, badStringError("bad Content-Length", cl)
1069 }
1070 return int64(n), nil
1071 }
1072
1073
1074
1075 type finishAsyncByteRead struct {
1076 tw *transferWriter
1077 }
1078
1079 func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) {
1080 if len(p) == 0 {
1081 return
1082 }
1083 rres := <-fr.tw.ByteReadCh
1084 n, err = rres.n, rres.err
1085 if n == 1 {
1086 p[0] = rres.b
1087 }
1088 if err == nil {
1089 err = io.EOF
1090 }
1091 return
1092 }
1093
1094 var nopCloserType = reflect.TypeOf(io.NopCloser(nil))
1095 var nopCloserWriterToType = reflect.TypeOf(io.NopCloser(struct {
1096 io.Reader
1097 io.WriterTo
1098 }{}))
1099
1100
1101
1102 func unwrapNopCloser(r io.Reader) (underlyingReader io.Reader, isNopCloser bool) {
1103 switch reflect.TypeOf(r) {
1104 case nopCloserType, nopCloserWriterToType:
1105 return reflect.ValueOf(r).Field(0).Interface().(io.Reader), true
1106 default:
1107 return nil, false
1108 }
1109 }
1110
1111
1112
1113
1114 func isKnownInMemoryReader(r io.Reader) bool {
1115 switch r.(type) {
1116 case *bytes.Reader, *bytes.Buffer, *strings.Reader:
1117 return true
1118 }
1119 if r, ok := unwrapNopCloser(r); ok {
1120 return isKnownInMemoryReader(r)
1121 }
1122 if r, ok := r.(*readTrackingBody); ok {
1123 return isKnownInMemoryReader(r.ReadCloser)
1124 }
1125 return false
1126 }
1127
1128
1129
1130 type bufioFlushWriter struct{ w io.Writer }
1131
1132 func (fw bufioFlushWriter) Write(p []byte) (n int, err error) {
1133 n, err = fw.w.Write(p)
1134 if bw, ok := fw.w.(*bufio.Writer); n > 0 && ok {
1135 ferr := bw.Flush()
1136 if ferr != nil && err == nil {
1137 err = ferr
1138 }
1139 }
1140 return
1141 }
1142
View as plain text