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