json - 使用 net/http 在 PUT "Body length 0"上出现错误

标签 json http docker go docker-registry

我在我的应用程序上使用这个 Go API 客户端 https://github.com/heroku/docker-registry-client使用 Go 与 docker registry 交互。这种情况是在使用包“net/http”进行 PUT 请求时在内部遇到一些问题。

当我运行以下代码时,出现错误 Put url: http: ContentLength=2821 with Body length 0。所以看起来 net/http Client.Do() 函数没有得到我在函数的某个点设置的主体。但是正如您在下面的代码中看到的那样,我仍然有我想要在 []byte 中发送的 JSON 内容。

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

据我深入研究,错误来自 net/http Client.do() 函数(golang.org/src/net/http/client.go 第 514 行) ,我会说错误是由 Request.GetBody() 函数触发的(来自客户端的第 591 行)。

所以仍然试图更深入地做一些测试来找出这里发生了什么。

有什么线索吗?

如果错误是由服务器给出的,我必须得到这样的东西,但在响应主体中并且在 net/http Client.Do() 调用上没有错误。

Content-Length: <length>
Content-Type: application/json; charset=utf-8

{
    "errors:" [
        {
            "code": <error code>,
            "message": "<error message>",
            "detail": ...
        },
        ...
    ]
}

非常感谢!

干杯

最佳答案

问题在 https://github.com/heroku/docker-registry-client 中修改 RoundTripper在获取身份验证 token 后对注册表进行重定向调用。当它尝试将调用重定向到注册表时,正文为空,因为 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)

关于json - 使用 net/http 在 PUT "Body length 0"上出现错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52429036/

相关文章:

ruby-on-rails - Rails escape_javascript通过转义单引号来创建无效的JSON

python - 如何使用 Tornado 设置自定义服务器 header ?

docker - 错误 : Cannot Start Container: stat/bin/sh: no such file or directory"

mysql - 可以使用git同步不同机器上的docker容器吗?

java - Jackson 对第 3 方类进行序列化和反序列化,无需编写自定义序列化器和/或反序列化器

java - 如何在 StringBuilder 中将项目与 JsonObject 分开?

将 elisp unixtime 转换为 js-date 对象

http - ionic 2 : stop an http request

java - 我有什么办法可以标记“仅在重试后才能成功”的任务?

php - 在 Nginx 反向代理后面运行 Apache(使用 .htaccess)应用程序