diff --git a/googleapi/googleapi.go b/googleapi/googleapi.go index 6818b2de30..c3e8a4f591 100644 --- a/googleapi/googleapi.go +++ b/googleapi/googleapi.go @@ -145,22 +145,40 @@ func CheckResponse(res *http.Response) error { } slurp, err := io.ReadAll(res.Body) if err == nil { - jerr := new(errorReply) - err = json.Unmarshal(slurp, jerr) - if err == nil && jerr.Error != nil { - if jerr.Error.Code == 0 { - jerr.Error.Code = res.StatusCode - } - jerr.Error.Body = string(slurp) - jerr.Error.Header = res.Header - return jerr.Error - } + return CheckResponseWithBody(res, slurp) } return &Error{ Code: res.StatusCode, Body: string(slurp), Header: res.Header, } + +} + +// CheckResponseWithBody returns an error (of type *Error) if the response +// status code is not 2xx. Distinct from CheckResponse to allow for checking +// a previously-read body to maintain error detail content. +func CheckResponseWithBody(res *http.Response, body []byte) error { + if res.StatusCode >= 200 && res.StatusCode <= 299 { + return nil + } + + jerr := new(errorReply) + err := json.Unmarshal(body, jerr) + if err == nil && jerr.Error != nil { + if jerr.Error.Code == 0 { + jerr.Error.Code = res.StatusCode + } + jerr.Error.Body = string(body) + jerr.Error.Header = res.Header + return jerr.Error + } + + return &Error{ + Code: res.StatusCode, + Body: string(body), + Header: res.Header, + } } // IsNotModified reports whether err is the result of the diff --git a/googleapi/googleapi_test.go b/googleapi/googleapi_test.go index db06aa273e..25b5de2a9b 100644 --- a/googleapi/googleapi_test.go +++ b/googleapi/googleapi_test.go @@ -339,6 +339,32 @@ func TestCheckResponse(t *testing.T) { } } +func TestCheckResponseWithBody(t *testing.T) { + for _, test := range checkResponseTests { + res := test.in + var body []byte + if test.bodyText != "" { + body = []byte(test.bodyText) + } + g := CheckResponseWithBody(res, body) + if !reflect.DeepEqual(g, test.want) { + t.Errorf("CheckResponse: got %v, want %v", g, test.want) + gotJSON, err := json.Marshal(g) + if err != nil { + t.Error(err) + } + wantJSON, err := json.Marshal(test.want) + if err != nil { + t.Error(err) + } + t.Errorf("json(got): %q\njson(want): %q", string(gotJSON), string(wantJSON)) + } + if g != nil && g.Error() != test.errText { + t.Errorf("CheckResponse: unexpected error message.\nGot: %q\nwant: %q", g, test.errText) + } + } +} + type VariantPoint struct { Type string Coordinates []float64