From 27765f9987976ac20c420800a50cd5253df4afe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Montes?= Date: Fri, 7 Aug 2020 09:01:24 +0200 Subject: [PATCH] Generalize REST error parsing --- pkg/cmd/api/api.go | 38 +++++++++++++++++++++++++++++--------- pkg/cmd/api/api_test.go | 11 +++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/pkg/cmd/api/api.go b/pkg/cmd/api/api.go index 8900f3f39..27810187b 100644 --- a/pkg/cmd/api/api.go +++ b/pkg/cmd/api/api.go @@ -426,23 +426,43 @@ func parseErrorResponse(r io.Reader, statusCode int) (io.Reader, string, error) var parsedBody struct { Message string - Errors []struct { - Message string - } + Errors []json.RawMessage } err = json.Unmarshal(b, &parsedBody) if err != nil { return r, "", err } - if parsedBody.Message != "" { return bodyCopy, fmt.Sprintf("%s (HTTP %d)", parsedBody.Message, statusCode), nil - } else if len(parsedBody.Errors) > 0 { - msgs := make([]string, len(parsedBody.Errors)) - for i, e := range parsedBody.Errors { - msgs[i] = e.Message + } + + type errorMessage struct { + Message string + } + var errors []string + for _, rawErr := range parsedBody.Errors { + if len(rawErr) == 0 { + continue } - return bodyCopy, strings.Join(msgs, "\n"), nil + if rawErr[0] == '{' { + var objectError errorMessage + err := json.Unmarshal(rawErr, &objectError) + if err != nil { + return r, "", err + } + errors = append(errors, objectError.Message) + } else if rawErr[0] == '"' { + var stringError string + err := json.Unmarshal(rawErr, &stringError) + if err != nil { + return r, "", err + } + errors = append(errors, stringError) + } + } + + if len(errors) > 0 { + return bodyCopy, strings.Join(errors, "\n"), nil } return bodyCopy, "", nil diff --git a/pkg/cmd/api/api_test.go b/pkg/cmd/api/api_test.go index f590d93b4..e5aa9f31d 100644 --- a/pkg/cmd/api/api_test.go +++ b/pkg/cmd/api/api_test.go @@ -264,6 +264,17 @@ func Test_apiRun(t *testing.T) { stdout: `{"message": "THIS IS FINE"}`, stderr: "gh: THIS IS FINE (HTTP 400)\n", }, + { + name: "REST string errors", + httpResponse: &http.Response{ + StatusCode: 400, + Body: ioutil.NopCloser(bytes.NewBufferString(`{"errors": ["ALSO", "FINE"]}`)), + Header: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}}, + }, + err: cmdutil.SilentError, + stdout: `{"errors": ["ALSO", "FINE"]}`, + stderr: "gh: ALSO\nFINE\n", + }, { name: "GraphQL error", options: ApiOptions{