diff --git a/internal/client/errors.go b/internal/client/errors.go index 4077f373e..5131ef813 100644 --- a/internal/client/errors.go +++ b/internal/client/errors.go @@ -46,8 +46,14 @@ func parseHTTPErrorResponse(resp *http.Response) error { } statusCode := resp.StatusCode - ctHeader := resp.Header.Get("Content-Type") + // A HEAD request for example validly does not contain any body, while + // still returning a JSON content-type. + if len(body) == 0 { + return makeError(statusCode, "") + } + + ctHeader := resp.Header.Get("Content-Type") if ctHeader == "" { return makeError(statusCode, string(body)) } diff --git a/internal/client/errors_test.go b/internal/client/errors_test.go index 432e2bcc0..e7a285cd9 100644 --- a/internal/client/errors_test.go +++ b/internal/client/errors_test.go @@ -57,6 +57,22 @@ func TestHandleHTTPResponseError401WithInvalidBody(t *testing.T) { } } +func TestHandleHTTPResponseError401WithNoBody(t *testing.T) { + json := "" + response := &http.Response{ + Status: "401 Unauthorized", + StatusCode: 401, + Body: nopCloser{bytes.NewBufferString(json)}, + Header: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}}, + } + err := HandleHTTPResponseError(response) + + expectedMsg := "unauthorized: " + if !strings.Contains(err.Error(), expectedMsg) { + t.Errorf("Expected %q, got: %q", expectedMsg, err.Error()) + } +} + func TestHandleHTTPResponseErrorExpectedStatusCode400ValidBody(t *testing.T) { json := `{"errors":[{"code":"DIGEST_INVALID","message":"provided digest does not match"}]}` response := &http.Response{