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, maxTrailerHeaders)
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, maxHeaders int64) (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 for _, v := range vv {
792 maxHeaders -= int64(strings.Count(v, ",") + 1)
793 if maxHeaders < 0 {
794 return nil, errTooLarge
795 }
796 }
797
798 trailer := make(Header)
799 var err error
800 for _, v := range vv {
801 foreachHeaderElement(v, func(key string) {
802 key = CanonicalHeaderKey(key)
803 switch key {
804 case "Transfer-Encoding", "Trailer", "Content-Length":
805 if err == nil {
806 err = badStringError("bad trailer key", key)
807 return
808 }
809 }
810 trailer[key] = nil
811 })
812 }
813 if err != nil {
814 return nil, err
815 }
816 if len(trailer) == 0 {
817 return nil, nil
818 }
819 return trailer, nil
820 }
821
822
823
824
825 type body struct {
826 src io.Reader
827 hdr any
828 r *bufio.Reader
829 closing bool
830 doEarlyClose bool
831 maxTrailerHeaders int64
832
833 mu sync.Mutex
834 sawEOF bool
835 closed bool
836 earlyClose bool
837 dropTrailer bool
838 onHitEOF func()
839 }
840
841
842
843
844
845 var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
846
847 func (b *body) Read(p []byte) (n int, err error) {
848 if b == nil {
849 return 0, io.EOF
850 }
851 b.mu.Lock()
852 defer b.mu.Unlock()
853 if b.closed {
854 return 0, ErrBodyReadAfterClose
855 }
856 return b.readLocked(p)
857 }
858
859
860 func (b *body) readLocked(p []byte) (n int, err error) {
861 if b.sawEOF {
862 return 0, io.EOF
863 }
864 n, err = b.src.Read(p)
865
866 if err == io.EOF {
867 b.sawEOF = true
868
869 if b.hdr != nil {
870 if e := b.readTrailer(); e != nil {
871 err = e
872
873
874
875
876 b.sawEOF = false
877 b.closed = true
878 }
879 b.hdr = nil
880 } else {
881
882
883 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > 0 {
884 err = io.ErrUnexpectedEOF
885 }
886 }
887 }
888
889
890
891
892
893
894 if err == nil && n > 0 {
895 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N == 0 {
896 err = io.EOF
897 b.sawEOF = true
898 }
899 }
900
901 if b.sawEOF && b.onHitEOF != nil {
902 b.onHitEOF()
903 }
904
905 return n, err
906 }
907
908 var (
909 singleCRLF = []byte("\r\n")
910 doubleCRLF = []byte("\r\n\r\n")
911 )
912
913 func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
914 for peekSize := 4; ; peekSize++ {
915
916
917 buf, err := r.Peek(peekSize)
918 if bytes.HasSuffix(buf, doubleCRLF) {
919 return true
920 }
921 if err != nil {
922 break
923 }
924 }
925 return false
926 }
927
928 var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
929
930 func (b *body) readTrailer() error {
931
932 buf, err := b.r.Peek(2)
933 if bytes.Equal(buf, singleCRLF) {
934 b.r.Discard(2)
935 return nil
936 }
937 if len(buf) < 2 {
938 return errTrailerEOF
939 }
940 if err != nil {
941 return err
942 }
943
944
945
946
947
948
949
950
951
952 if !seeUpcomingDoubleCRLF(b.r) {
953 return errors.New("http: suspiciously long trailer after chunked body")
954 }
955
956 hdr, err := readMIMEHeader(textproto.NewReader(b.r), math.MaxInt64, b.maxTrailerHeaders)
957 if err != nil {
958 if err == io.EOF {
959 return errTrailerEOF
960 }
961 return err
962 }
963
964
965
966
967 if b.dropTrailer {
968 return nil
969 }
970 switch rr := b.hdr.(type) {
971 case *Request:
972 mergeSetHeader(&rr.Trailer, Header(hdr))
973 case *Response:
974 mergeSetHeader(&rr.Trailer, Header(hdr))
975 }
976 return nil
977 }
978
979 func mergeSetHeader(dst *Header, src Header) {
980 if *dst == nil {
981 *dst = src
982 return
983 }
984 maps.Copy(*dst, src)
985 }
986
987 func (b *body) discardTrailer() {
988 b.mu.Lock()
989 defer b.mu.Unlock()
990 b.dropTrailer = true
991 }
992
993
994
995
996 func (b *body) unreadDataSizeLocked() int64 {
997 if lr, ok := b.src.(*io.LimitedReader); ok {
998 return lr.N
999 }
1000 return -1
1001 }
1002
1003 func (b *body) Close() error {
1004 if b == nil {
1005 return nil
1006 }
1007 b.mu.Lock()
1008 defer b.mu.Unlock()
1009 if b.closed {
1010 return nil
1011 }
1012 var err error
1013 switch {
1014 case b.sawEOF:
1015
1016 case b.hdr == nil && b.closing:
1017
1018
1019 case b.doEarlyClose:
1020
1021
1022 if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > maxPostHandlerReadBytes {
1023
1024
1025 b.earlyClose = true
1026 } else {
1027 var n int64
1028
1029
1030 n, err = io.CopyN(io.Discard, bodyLocked{b}, maxPostHandlerReadBytes+1)
1031 b.earlyClose = true
1032 if err == io.EOF && n <= maxPostHandlerReadBytes {
1033 b.earlyClose = false
1034 b.sawEOF = true
1035
1036
1037 err = nil
1038 }
1039 }
1040 default:
1041
1042
1043 _, err = io.Copy(io.Discard, bodyLocked{b})
1044 }
1045 b.closed = true
1046 return err
1047 }
1048
1049 func (b *body) didEarlyClose() bool {
1050 b.mu.Lock()
1051 defer b.mu.Unlock()
1052 return b.earlyClose
1053 }
1054
1055
1056
1057 func (b *body) bodyRemains() bool {
1058 if b == nil {
1059 return false
1060 }
1061 b.mu.Lock()
1062 defer b.mu.Unlock()
1063 return !b.sawEOF
1064 }
1065
1066 func (b *body) registerOnHitEOF(fn func()) {
1067 if b == nil {
1068 return
1069 }
1070 b.mu.Lock()
1071 defer b.mu.Unlock()
1072 b.onHitEOF = fn
1073 }
1074
1075
1076
1077 type bodyLocked struct {
1078 b *body
1079 }
1080
1081 func (bl bodyLocked) Read(p []byte) (n int, err error) {
1082 if bl.b.closed {
1083 return 0, ErrBodyReadAfterClose
1084 }
1085 return bl.b.readLocked(p)
1086 }
1087
1088 var httplaxcontentlength = godebug.New("httplaxcontentlength")
1089
1090
1091
1092
1093 func parseContentLength(clHeaders []string) (int64, error) {
1094 if len(clHeaders) == 0 {
1095 return -1, nil
1096 }
1097 cl := textproto.TrimString(clHeaders[0])
1098
1099
1100
1101 if cl == "" {
1102 if httplaxcontentlength.Value() == "1" {
1103 httplaxcontentlength.IncNonDefault()
1104 return -1, nil
1105 }
1106 return 0, badStringError("invalid empty Content-Length", cl)
1107 }
1108 n, err := strconv.ParseUint(cl, 10, 63)
1109 if err != nil {
1110 return 0, badStringError("bad Content-Length", cl)
1111 }
1112 return int64(n), nil
1113 }
1114
1115
1116
1117 type finishAsyncByteRead struct {
1118 tw *transferWriter
1119 }
1120
1121 func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) {
1122 if len(p) == 0 {
1123 return
1124 }
1125 rres := <-fr.tw.ByteReadCh
1126 n, err = rres.n, rres.err
1127 if n == 1 {
1128 p[0] = rres.b
1129 }
1130 if err == nil {
1131 err = io.EOF
1132 }
1133 return
1134 }
1135
1136 var nopCloserType = reflect.TypeOf(io.NopCloser(nil))
1137 var nopCloserWriterToType = reflect.TypeOf(io.NopCloser(struct {
1138 io.Reader
1139 io.WriterTo
1140 }{}))
1141
1142
1143
1144 func unwrapNopCloser(r io.Reader) (underlyingReader io.Reader, isNopCloser bool) {
1145 switch reflect.TypeOf(r) {
1146 case nopCloserType, nopCloserWriterToType:
1147 return reflect.ValueOf(r).Field(0).Interface().(io.Reader), true
1148 default:
1149 return nil, false
1150 }
1151 }
1152
1153
1154
1155
1156 func isKnownInMemoryReader(r io.Reader) bool {
1157 switch r.(type) {
1158 case *bytes.Reader, *bytes.Buffer, *strings.Reader:
1159 return true
1160 }
1161 if r, ok := unwrapNopCloser(r); ok {
1162 return isKnownInMemoryReader(r)
1163 }
1164 if r, ok := r.(*readTrackingBody); ok {
1165 return isKnownInMemoryReader(r.ReadCloser)
1166 }
1167 return false
1168 }
1169
1170
1171
1172 type bufioFlushWriter struct{ w io.Writer }
1173
1174 func (fw bufioFlushWriter) Write(p []byte) (n int, err error) {
1175 n, err = fw.w.Write(p)
1176 if bw, ok := fw.w.(*bufio.Writer); n > 0 && ok {
1177 ferr := bw.Flush()
1178 if ferr != nil && err == nil {
1179 err = ferr
1180 }
1181 }
1182 return
1183 }
1184
View as plain text