Skip to content

Commit

Permalink
Include response body in non-200 OK error text.
Browse files Browse the repository at this point in the history
When a GraphQL server returns a non-200 OK status code, it may be
very helpful to for caller to know what the response body was.
So, when such an error occurs, fetch the response body and
include it in the returned error text.

Fixes #29.
Updates #24.
  • Loading branch information
dmitshur committed Sep 24, 2018
1 parent 3658993 commit e4a3a37
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
6 changes: 5 additions & 1 deletion graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"

"github.com/shurcooL/go/ctxhttp"
Expand Down Expand Up @@ -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
Expand All @@ -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
}
}
Expand Down
24 changes: 24 additions & 0 deletions graphql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit e4a3a37

Please sign in to comment.