我正在我的应用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()
非常感谢您!
欢呼
答案 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)