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