diff --git a/graphql.go b/graphql.go index f2c5b54..e0248fd 100644 --- a/graphql.go +++ b/graphql.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "io/ioutil" "net/http" "github.com/shurcooL/go/ctxhttp" @@ -70,7 +71,8 @@ func (c *Client) do(ctx context.Context, op operationType, v interface{}, variab } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return fmt.Errorf("unexpected status: %v", resp.Status) + body, _ := ioutil.ReadAll(resp.Body) + return fmt.Errorf("non-200 OK status code: %v body: %q", resp.Status, body) } var out struct { Data *json.RawMessage @@ -79,11 +81,13 @@ func (c *Client) do(ctx context.Context, op operationType, v interface{}, variab } err = json.NewDecoder(resp.Body).Decode(&out) if err != nil { + // TODO: Consider including response body in returned error, if deemed helpful. return err } if out.Data != nil { err := jsonutil.UnmarshalGraphQL(*out.Data, v) if err != nil { + // TODO: Consider including response body in returned error, if deemed helpful. return err } } diff --git a/graphql_test.go b/graphql_test.go index 4262c3f..e09dcc9 100644 --- a/graphql_test.go +++ b/graphql_test.go @@ -101,6 +101,30 @@ func TestClient_Query_noDataWithErrorResponse(t *testing.T) { } } +func TestClient_Query_errorStatusCode(t *testing.T) { + mux := http.NewServeMux() + mux.HandleFunc("/graphql", func(w http.ResponseWriter, req *http.Request) { + http.Error(w, "important message", http.StatusInternalServerError) + }) + client := graphql.NewClient("/graphql", &http.Client{Transport: localRoundTripper{handler: mux}}) + + var q struct { + User struct { + Name graphql.String + } + } + err := client.Query(context.Background(), &q, nil) + if err == nil { + t.Fatal("got error: nil, want: non-nil") + } + if got, want := err.Error(), `non-200 OK status code: 500 Internal Server Error body: "important message\n"`; got != want { + t.Errorf("got error: %v, want: %v", got, want) + } + if q.User.Name != "" { + t.Errorf("got non-empty q.User.Name: %v", q.User.Name) + } +} + // Test that an empty (but non-nil) variables map is // handled no differently than a nil variables map. func TestClient_Query_emptyVariables(t *testing.T) {