diff options
Diffstat (limited to 'libgo/go/net/http/transfer.go')
-rw-r--r-- | libgo/go/net/http/transfer.go | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/libgo/go/net/http/transfer.go b/libgo/go/net/http/transfer.go index 4f47637aa76..8faff2d74a6 100644 --- a/libgo/go/net/http/transfer.go +++ b/libgo/go/net/http/transfer.go @@ -51,6 +51,19 @@ func (br *byteReader) Read(p []byte) (n int, err error) { return 1, io.EOF } +// transferBodyReader is an io.Reader that reads from tw.Body +// and records any non-EOF error in tw.bodyReadError. +// It is exactly 1 pointer wide to avoid allocations into interfaces. +type transferBodyReader struct{ tw *transferWriter } + +func (br transferBodyReader) Read(p []byte) (n int, err error) { + n, err = br.tw.Body.Read(p) + if err != nil && err != io.EOF { + br.tw.bodyReadError = err + } + return +} + // transferWriter inspects the fields of a user-supplied Request or Response, // sanitizes them without changing the user object and provides methods for // writing the respective header, body and trailer in wire format. @@ -62,8 +75,10 @@ type transferWriter struct { ContentLength int64 // -1 means unknown, 0 means exactly none Close bool TransferEncoding []string + Header Header Trailer Header IsResponse bool + bodyReadError error // any non-EOF error from reading Body FlushHeaders bool // flush headers to network before body ByteReadCh chan readResult // non-nil if probeRequestBody called @@ -82,14 +97,15 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) { t.Method = valueOrDefault(rr.Method, "GET") t.Close = rr.Close t.TransferEncoding = rr.TransferEncoding + t.Header = rr.Header t.Trailer = rr.Trailer - atLeastHTTP11 = rr.protoAtLeastOutgoing(1, 1) t.Body = rr.Body t.BodyCloser = rr.Body t.ContentLength = rr.outgoingLength() - if t.ContentLength < 0 && len(t.TransferEncoding) == 0 && atLeastHTTP11 && t.shouldSendChunkedRequestBody() { + if t.ContentLength < 0 && len(t.TransferEncoding) == 0 && t.shouldSendChunkedRequestBody() { t.TransferEncoding = []string{"chunked"} } + atLeastHTTP11 = true // Transport requests are always 1.1 or 2.0 case *Response: t.IsResponse = true if rr.Request != nil { @@ -100,6 +116,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) { t.ContentLength = rr.ContentLength t.Close = rr.Close t.TransferEncoding = rr.TransferEncoding + t.Header = rr.Header t.Trailer = rr.Trailer atLeastHTTP11 = rr.ProtoAtLeast(1, 1) t.ResponseToHEAD = noResponseBodyExpected(t.Method) @@ -252,7 +269,7 @@ func (t *transferWriter) shouldSendContentLength() bool { } func (t *transferWriter) WriteHeader(w io.Writer) error { - if t.Close { + if t.Close && !hasToken(t.Header.get("Connection"), "close") { if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil { return err } @@ -304,24 +321,25 @@ func (t *transferWriter) WriteBody(w io.Writer) error { // Write body if t.Body != nil { + var body = transferBodyReader{t} if chunked(t.TransferEncoding) { if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse { w = &internal.FlushAfterChunkWriter{Writer: bw} } cw := internal.NewChunkedWriter(w) - _, err = io.Copy(cw, t.Body) + _, err = io.Copy(cw, body) if err == nil { err = cw.Close() } } else if t.ContentLength == -1 { - ncopy, err = io.Copy(w, t.Body) + ncopy, err = io.Copy(w, body) } else { - ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength)) + ncopy, err = io.Copy(w, io.LimitReader(body, t.ContentLength)) if err != nil { return err } var nextra int64 - nextra, err = io.Copy(ioutil.Discard, t.Body) + nextra, err = io.Copy(ioutil.Discard, body) ncopy += nextra } if err != nil { |