Strange corruption of compressed archives in Golang.

I found that .tar.xz files downloaded from a remote http server were always corrupted (strangely .zip files were fine) in a Golang command line program I was writing, occurring with both fasthttp and net/http.

Making a request directly with http.Get(url) worked correctly.

resp, err := http.Get(url)
if err != nil {
	panic(err)
}
f, _ := os.OpenFile("data.tar.xz", os.O_CREATE|os.O_RDWR, 0666)
io.Copy(f, resp.Body)
f.Close()
resp.Body.Close()
// normal work.

Using wrappers like resty, or fasthttp without streaming enabled, they would corrupt .tar.xz archives.

// fasthttp
req, resp := fasthttp.AcquireRequest(), fasthttp.AcquireResponse()
req.SetRequestURI(url)
req.Header.SetMethod("GET")
if err := fasthttp.Do(req, resp); err != nil {
	panic(err)
}
f, _ := os.OpenFile("data.tar.xz", os.O_CREATE|os.O_RDWR, 0666)
resp.WriteTo(f) //...
//or
f.Write(resp.Body()
f.Close()
// .....
// Got a corrupt .tar.xz archive.
// After removing .xz, only .tar remains. 7zip can correctly identify it, 
// but the type still remains as "xz".

Enabling streaming Body for fasthttp resulted in getting a valid archive.

req, resp := fasthttp.AcquireRequest(), fasthttp.AcquireResponse()
req.SetRequestURI(url)
req.Header.SetMethod("GET")
resp.StreamBody = true
if err := fasthttp.Do(req, resp); err != nil {
	panic(err)
}
f, _ := os.OpenFile("data.tar.xz", os.O_CREATE|os.O_RDWR, 0666)
io.Copy(f, resp.BodyStream())
resp.CloseBodyStream()
resp.ReleaseBody(0)
f.Close()
// It's normal this time.

I didn't dig deeper into why this was happening, I confirmed my usage was correct, but it just wouldn't work properly. For a while before fixing this issue I was even using os/exec to just let wget and tar handle it, which was terrible.

🙏🙏🙏

Since you've made it this far, sharing this article on your favorite social media network would be highly appreciated 💖! For feedback, please ping me on Github.

Published