Получение ошибки на PUT "Длина тела 0" с использованием net / http - PullRequest
0 голосов
/ 20 сентября 2018

Я использую этот клиент Go API в своем приложении https://github.com/heroku/docker-registry-client для взаимодействия с реестром докера с помощью Go.Дело в том, что внутренне возникают некоторые проблемы, когда PUT-запрос использует пакет «net / http».

Когда я запускаю следующий код, я получаю это как ошибку Put url: http: ContentLength=2821 with Body length 0.Поэтому кажется, что функция net / http Client.Do () не получает тело, которое я установил в какой-то момент функции.Но, как вы можете видеть прямо в коде ниже, в какой-то момент у меня все еще есть контент JSON, который я хочу отправить в []byte.

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 на клиенте).

Так что все еще пытаюсь пойти глубже и сделать несколько тестов, чтобы выяснить, что здесь происходит.

Любая подсказка?

В случае, если сервер выдает ошибку, мне нужно получить что-то вроде этого, но в теле ответа и без ошибок в сети / http Client.Do()Звоните.

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

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

Большое вам спасибо!

Приветствия

1 Ответ

0 голосов
/ 19 октября 2018

Проблема модифицирована RoundTripper в https://github.com/heroku/docker-registry-client делает перенаправление вызова в реестр после получения токена аутентификации. Когда он пытается перенаправить вызов в реестр, тело пусто, потому что тело 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)
...