From 816976066868f749efef02a3ac8a4a6a6e5a3949 Mon Sep 17 00:00:00 2001 From: Henry Date: Sat, 18 Sep 2021 21:56:55 -0700 Subject: [PATCH] added better support for automatic decompression by updating the method with the latest code from the original net/http package. It avoids a problem where if the server sends an empty Content-Length then the old code would fail on decompression. Now if the cs.requestGzip is false, it won't bother decompressing and leave it up to the user as it should. --- h2_bundle.go | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/h2_bundle.go b/h2_bundle.go index dd968f67..cd9fdd48 100644 --- a/h2_bundle.go +++ b/h2_bundle.go @@ -49,7 +49,7 @@ import ( "sync" "sync/atomic" "time" - + "compress/gzip" "github.com/useflyent/fhttp/http2/hpack" "github.com/useflyent/fhttp/httptrace" "golang.org/x/net/http/httpguts" @@ -8976,10 +8976,41 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http cs.bytesRemain = res.ContentLength res.Body = http2transportResponseBody{cs} go cs.awaitRequestCancel(cs.req) - - res.Body = DecompressBody(res) + if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" { + res.Header.Del("Content-Encoding") + res.Header.Del("Content-Length") + res.ContentLength = -1 + res.Body = &http2gzipReader{body: res.Body} + res.Uncompressed = true + } return res, nil } +// gzipReader wraps a response body so it can lazily +// call gzip.NewReader on the first call to Read +type http2gzipReader struct { + _ http2incomparable + body io.ReadCloser // underlying Response.Body + zr *gzip.Reader // lazily-initialized gzip reader + zerr error // sticky error +} +func (gz *http2gzipReader) Read(p []byte) (n int, err error) { + if gz.zerr != nil { + return 0, gz.zerr + } + if gz.zr == nil { + gz.zr, err = gzip.NewReader(gz.body) + if err != nil { + gz.zerr = err + return 0, err + } + } + return gz.zr.Read(p) +} + +func (gz *http2gzipReader) Close() error { + return gz.body.Close() +} + func (rl *http2clientConnReadLoop) processTrailers(cs *http2clientStream, f *http2MetaHeadersFrame) error { if cs.pastTrailers {