2 minutes
Handling Gzip-Compressed Responses in Go
When working with HTTP APIs that return large payloads, it’s a common practice to compress responses using Gzip to reduce bandwidth and latency.
In Go, the HTTP client automatically decompresses Gzip responses if you don’t explicitly set the Accept-Encoding: gzip
header. This behavior is convenient for most scenarios. However, if you manually add the Accept-Encoding
header, Go assumes you want to handle the decompression yourself.
Manually Handling Gzip Responses in Go
If you explicitly set the Accept-Encoding: gzip header, Go does not automatically decompress the response. You’ll need to handle it manually, like so:
client := &http.Client{}
req, err := http.NewRequest("GET", "http://httpbin.org/gzip", nil)
if err != nil {
fmt.Printf("Error creating request: %s\n", err)
return
}
req.Header.Add("Accept-Encoding", "gzip")
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error making request: %s\n", err)
return
}
defer resp.Body.Close()
if resp.Header.Get("Content-Encoding") == "gzip" {
fmt.Println("Response is GZIP compressed. Decompressing...")
gzipReader, err := gzip.NewReader(resp.Body)
if err != nil {
fmt.Printf("Error creating gzip reader: %s\n", err)
return
}
defer gzipReader.Close()
bodyBytes, err := io.ReadAll(gzipReader)
if err != nil {
fmt.Printf("Error reading decompressed response body: %s\n", err)
return
}
fmt.Println("Decompressed Response Body:")
fmt.Println(string(bodyBytes))
} else {
fmt.Println("Response is not GZIP compressed. Reading directly...")
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error reading response body: %s\n", err)
return
}
fmt.Println("Response Body:")
fmt.Println(string(bodyBytes))
}
Letting Go Handle Decompression Automatically
If you donβt set the Accept-Encoding header manually, Go will add it for you and take care of the decompression transparently. Here’s how that looks:
client := &http.Client{}
req, err := http.NewRequest("GET", "http://httpbin.org/gzip", nil)
if err != nil {
fmt.Printf("Error creating request: %s\n", err)
return
}
req.Header.Add("Accept-Encoding", "gzip")
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error making request: %s\n", err)
return
}
defer resp.Body.Close()
fmt.Println("Reading directly...")
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error reading response body: %s\n", err)
return
}
fmt.Println("Response Body:")
fmt.Println(string(bodyBytes))
Why Would You Handle Gzip Manually?
There are a few reasons why you might want to handle Gzip compression yourself:
- Custom decompression logic (e.g., streaming decompression for large files)
- Logging or inspecting raw response headers and body
- Working with APIs that use non-standard encodings
In most cases, however, letting Go manage it for you is the simpler and safer option.