@@ -551,6 +551,28 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
551
551
}
552
552
hasTrailers := trailers != ""
553
553
554
+ var body io.Reader = req .Body
555
+ contentLen := req .ContentLength
556
+ if req .Body != nil && contentLen == 0 {
557
+ // Test to see if it's actually zero or just unset.
558
+ var buf [1 ]byte
559
+ n , rerr := io .ReadFull (body , buf [:])
560
+ if rerr != nil && rerr != io .EOF {
561
+ contentLen = - 1
562
+ body = errorReader {rerr }
563
+ } else if n == 1 {
564
+ // Oh, guess there is data in this Body Reader after all.
565
+ // The ContentLength field just wasn't set.
566
+ // Stich the Body back together again, re-attaching our
567
+ // consumed byte.
568
+ contentLen = - 1
569
+ body = io .MultiReader (bytes .NewReader (buf [:]), body )
570
+ } else {
571
+ // Body is actually empty.
572
+ body = nil
573
+ }
574
+ }
575
+
554
576
cc .mu .Lock ()
555
577
if cc .closed || ! cc .canTakeNewRequestLocked () {
556
578
cc .mu .Unlock ()
@@ -559,7 +581,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
559
581
560
582
cs := cc .newStream ()
561
583
cs .req = req
562
- hasBody := req . Body != nil
584
+ hasBody := body != nil
563
585
564
586
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
565
587
if ! cc .t .disableCompression () &&
@@ -584,7 +606,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
584
606
// we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is
585
607
// sent by writeRequestBody below, along with any Trailers,
586
608
// again in form HEADERS{1}, CONTINUATION{0,})
587
- hdrs := cc .encodeHeaders (req , cs .requestedGzip , trailers )
609
+ hdrs := cc .encodeHeaders (req , cs .requestedGzip , trailers , contentLen )
588
610
cc .wmu .Lock ()
589
611
endStream := ! hasBody && ! hasTrailers
590
612
werr := cc .writeHeaders (cs .ID , endStream , hdrs )
@@ -605,7 +627,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
605
627
if hasBody {
606
628
bodyCopyErrc = make (chan error , 1 )
607
629
go func () {
608
- bodyCopyErrc <- cs .writeRequestBody (req .Body )
630
+ bodyCopyErrc <- cs .writeRequestBody (body , req .Body )
609
631
}()
610
632
}
611
633
@@ -705,7 +727,7 @@ func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, hdrs []byte)
705
727
// It doesn't escape to callers.
706
728
var errAbortReqBodyWrite = errors .New ("http2: aborting request body write" )
707
729
708
- func (cs * clientStream ) writeRequestBody (body io.ReadCloser ) (err error ) {
730
+ func (cs * clientStream ) writeRequestBody (body io.Reader , bodyCloser io. Closer ) (err error ) {
709
731
cc := cs .cc
710
732
sentEnd := false // whether we sent the final DATA frame w/ END_STREAM
711
733
buf := cc .frameScratchBuffer ()
@@ -716,7 +738,7 @@ func (cs *clientStream) writeRequestBody(body io.ReadCloser) (err error) {
716
738
// Request.Body is closed by the Transport,
717
739
// and in multiple cases: server replies <=299 and >299
718
740
// while still writing request body
719
- cerr := body .Close ()
741
+ cerr := bodyCloser .Close ()
720
742
if err == nil {
721
743
err = cerr
722
744
}
@@ -829,7 +851,7 @@ type badStringError struct {
829
851
func (e * badStringError ) Error () string { return fmt .Sprintf ("%s %q" , e .what , e .str ) }
830
852
831
853
// requires cc.mu be held.
832
- func (cc * ClientConn ) encodeHeaders (req * http.Request , addGzipHeader bool , trailers string ) []byte {
854
+ func (cc * ClientConn ) encodeHeaders (req * http.Request , addGzipHeader bool , trailers string , contentLength int64 ) []byte {
833
855
cc .hbuf .Reset ()
834
856
835
857
host := req .Host
@@ -855,7 +877,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
855
877
var didUA bool
856
878
for k , vv := range req .Header {
857
879
lowKey := strings .ToLower (k )
858
- if lowKey == "host" {
880
+ if lowKey == "host" || lowKey == "content-length" {
859
881
continue
860
882
}
861
883
if lowKey == "user-agent" {
@@ -876,6 +898,9 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
876
898
cc .writeHeader (lowKey , v )
877
899
}
878
900
}
901
+ if contentLength >= 0 {
902
+ cc .writeHeader ("content-length" , strconv .FormatInt (contentLength , 10 ))
903
+ }
879
904
if addGzipHeader {
880
905
cc .writeHeader ("accept-encoding" , "gzip" )
881
906
}
@@ -1605,3 +1630,7 @@ func (gz *gzipReader) Read(p []byte) (n int, err error) {
1605
1630
func (gz * gzipReader ) Close () error {
1606
1631
return gz .body .Close ()
1607
1632
}
1633
+
1634
+ type errorReader struct { err error }
1635
+
1636
+ func (r errorReader ) Read (p []byte ) (int , error ) { return 0 , r .err }
0 commit comments