使用Go http客户端时遇到意外的EOF

15

我正在学习 Go,并遇到了这个问题。

我只是使用 HTTP 客户端下载网页内容:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func main() {
    client := &http.Client{}

    req, err := http.NewRequest("GET", "https://mail.ru/", nil)
    req.Close = true

    response, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }

    defer response.Body.Close()

    content, err := ioutil.ReadAll(response.Body)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(string(content)[:100])
}

当读取响应正文时,我遇到了一个意外的EOF错误。与此同时,内容变量具有完整的页面内容。

只有在下载https://mail.ru/内容时才会出现此错误。对于其他URL,一切正常-没有任何错误。

我使用curl下载此页面内容-一切都按预期工作。

我有点困惑-这里发生了什么?

Go v1.2,在Ubuntu和MacOS X上尝试过


也许mail.ru返回了一个损坏的Content-Length?请手动检查整个响应。Curl“只是工作”,不会抱怨小问题。 - Volker
3
服务器没有发送Content-Length头,当它完成响应发送时,会简单地断开客户端连接。这会导致"unexpected EOF",因为客户端不知道会发生什么 - 但显然这是完全可以接受的。内容被完整接收。 - Not_a_Golfer
1
响应具有Content-Length头。我已经手动检查了Content-Length头的值和响应的实际长度 - 它们是相等的。 - Alex Emelin
奇怪,当我运行你的代码时,我没有得到一个。 - Not_a_Golfer
嗯...是的,这很奇怪,也许需要另一个Go版本? - Alex Emelin
1个回答

9

看起来那个服务器(Apache 1.3,哇!)提供了一个截断的gzip响应。如果你明确请求identity编码(防止Go传输自行添加gzip),你就不会得到ErrUnexpectedEOF

req.Header.Add("Accept-Encoding", "identity")

一旁注:如果没有明确禁用,则默认情况下可接受“identity”编码(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding#Directives)。 - miku

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接