使用net / http在PUT“主体长度0”上获取错误

时间:2018-09-20 15:59:45

标签: json http docker go docker-registry

我正在我的应用https://github.com/heroku/docker-registry-client上使用此Go API客户端,以使用Go与Docker注册表进行交互。这种情况是在内部使用软件包“ net / http”进行PUT请求时出现问题。

运行以下代码时,我将其作为错误desktop-view得到。因此,似乎net / http Client.Do()函数没有获得我在函数的某个位置设置的主体。但是,正如您可以正确地在下面的代码上看到的那样,我仍然具有要在Put url: http: ContentLength=2821 with Body length 0中发送的JSON内容。

[]byte

据我所知,错误来自net / http body, err := manifest.MarshalJSON() if err != nil { return err } log.Println(string(body)) // I get the JSON data back here req, err := http.NewRequest("PUT", url, bytes.NewReader(body)) if err != nil { return err } req.Header.Set("Content-Type", manifestV2.MediaTypeManifest) resp, err := registry.Client.Do(req) if resp != nil { defer resp.Body.Close() } return err 函数(golang.org/src/net/http/client.go 514行),我会说Client.do()函数(从客户端的第591行)触发了错误。

因此,仍要尝试更深入并进行一些测试,以了解此处发生的情况。

有任何线索吗?

如果服务器发出错误,则必须获得类似内容,但在响应正文中,net / http Request.GetBody()调用中不会出现错误。

Client.Do()

非常感谢您!

欢呼

1 个答案:

答案 0 :(得分:0)

已修改问题,https://github.com/heroku/docker-registry-client中的RoundTripper在获取身份验证令牌后向注册表进行了重定向调用。当它尝试将调用重定向到注册表时,body为空,因为http.request正文是一个缓冲区,一旦被读取在第一个调用中,缓冲区变为空,并且没有要发送的正文内容。

要解决此问题:

if req.Method == "PUT" || req.Method == "POST" {
    if req.Body != nil {
        reUseBody, _ = req.GetBody()
    }
}

将此添加到https://github.com/heroku/docker-registry-client/blob/master/registry/tokentransport.go#L17

if req.Method == "PUT" || req.Method == "POST" {
    if reUseBody != nil {
        req.Body = reUseBody
    } 
}

在这里https://github.com/heroku/docker-registry-client/blob/master/registry/tokentransport.go#L72

并更改此功能签名https://github.com/heroku/docker-registry-client/blob/master/registry/tokentransport.go#L71  接受额外的争论。

func (t *TokenTransport) retry(req *http.Request, token string, reUseBody io.ReadCloser)