我试图用Go读取一个gzip压缩的HTTP响应!但我总是收到以下错误消息:
panic: gzip: invalid header
[...] stack trace [...]
如果我运行“curl -H”接受编码:gzip“http://foo.com/ | gunzip - ”我得到了正确的枪杀响应。我还用ngrep进行了双重检查,正确发送/返回了一对Accept-Encoding / Content-Encoding。
如果我创建一个包含虚拟内容的文件并对其进行gzip,我可以从Go中读取它!程序
我用于测试的程序:
package main
import (
"io"
//"os"
"fmt"
"compress/gzip"
"net/http"
)
func main() {
/* This works fine
f, _ := os.Open("/tmp/test.gz")
defer f.Close()
reader, err := gzip.NewReader(f)
*/
// This does not :/
resp, _ := http.Get("http://foo.com/")
defer resp.Body.Close()
reader, err := gzip.NewReader(resp.Body)
if err != nil { panic(err) }
buff := make([]byte, 1024)
for {
n, err := reader.Read(buff)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
}
s := fmt.Sprintf("%s", buff)
fmt.Println(s)
}
我忽略了什么吗?
答案 0 :(得分:47)
编辑:以下是手动处理压缩的示例。如果您没有设置标题,默认的传输将为您执行此操作,然后在您阅读响应时解压缩.Body。
client := new(http.Client)
request, err := http.NewRequest("GET", "http://stackoverflow.com", nil)
request.Header.Add("Accept-Encoding", "gzip")
response, err := client.Do(request)
defer response.Body.Close()
// Check that the server actually sent compressed data
var reader io.ReadCloser
switch response.Header.Get("Content-Encoding") {
case "gzip":
reader, err = gzip.NewReader(response.Body)
defer reader.Close()
default:
reader = response.Body
}
io.Copy(os.Stdout, reader) // print html to standard out
为简洁起见,删除了错误处理。我坚持要求。
答案 1 :(得分:29)
net/http#Transport
处理gzip
压缩响应。你不需要做任何特别的事情。
答案 2 :(得分:8)
根据net/http docs (line 110),如果您手动设置 Accept-Encoding 请求标头,则gzip响应不会被http.Transport自动解压缩。否则,行为由Transport的 DisableCompression 布尔值
控制