Skip to content

Commit

Permalink
Return GraphQL compliant errors for http requests (#3728)
Browse files Browse the repository at this point in the history
(cherry picked from commit efb9387)
  • Loading branch information
MichaelJCompton committed Aug 8, 2019
1 parent 8ba4a85 commit 02375af
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 15 deletions.
9 changes: 2 additions & 7 deletions dgraph/cmd/alpha/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,10 @@ import (
"github.com/dgraph-io/dgraph/x"
)

type respError struct {
Code string `json:"code"`
Message string `json:"message"`
}

type res struct {
Data json.RawMessage `json:"data"`
Extensions *query.Extensions `json:"extensions,omitempty"`
Errors []respError `json:"errors,omitempty"`
Errors []x.GqlError `json:"errors,omitempty"`
}

type params struct {
Expand Down Expand Up @@ -466,7 +461,7 @@ func TestAlterAllFieldsShouldBeSet(t *testing.T) {
var qr x.QueryResWithData
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &qr))
require.Len(t, qr.Errors, 1)
require.Equal(t, qr.Errors[0].Code, "Error")
require.Equal(t, qr.Errors[0].Extensions["code"], "Error")
}

func TestHttpCompressionSupport(t *testing.T) {
Expand Down
41 changes: 33 additions & 8 deletions x/x.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,43 @@ func ShouldCrash(err error) bool {
// WhiteSpace Replacer removes spaces and tabs from a string.
var WhiteSpace = strings.NewReplacer(" ", "", "\t", "")

type errRes struct {
Code string `json:"code"`
Message string `json:"message"`
// GqlError is a GraphQL spec compliant error structure. See GraphQL spec on
// errors here: https://graphql.github.io/graphql-spec/June2018/#sec-Errors
//
// Note: "Every error must contain an entry with the key message with a string
// description of the error intended for the developer as a guide to understand
// and correct the error."
//
// "If an error can be associated to a particular point in the request [the error]
// should contain an entry with the key locations with a list of locations"
//
// Path is about GraphQL results and Errors for GraphQL layer.
//
// Extensions is for everything else.
type GqlError struct {
Message string `json:"message"`
Locations []Location `json:"locations,omitempty"`
Path []interface{} `json:"path,omitempty"`
Extensions map[string]interface{} `json:"extensions,omitempty"`
}

// A Location is the Line+Column index of an error in a request.
type Location struct {
Line int `json:"line,omitempty"`
Column int `json:"column,omitempty"`
}

type queryRes struct {
Errors []errRes `json:"errors"`
Errors []GqlError `json:"errors"`
}

// SetStatus sets the error code, message and the newly assigned uids
// in the http response.
func SetStatus(w http.ResponseWriter, code, msg string) {
var qr queryRes
qr.Errors = append(qr.Errors, errRes{Code: code, Message: msg})
ext := make(map[string]interface{})
ext["code"] = code
qr.Errors = append(qr.Errors, GqlError{Message: msg, Extensions: ext})
if js, err := json.Marshal(qr); err == nil {
if _, err := w.Write(js); err != nil {
glog.Errorf("Error while writing: %+v", err)
Expand Down Expand Up @@ -170,8 +193,8 @@ func AddCorsHeaders(w http.ResponseWriter) {

// QueryResWithData represents a response that holds errors as well as data.
type QueryResWithData struct {
Errors []errRes `json:"errors"`
Data *string `json:"data"`
Errors []GqlError `json:"errors"`
Data *string `json:"data"`
}

// SetStatusWithData sets the errors in the response and ensures that the data key
Expand All @@ -180,7 +203,9 @@ type QueryResWithData struct {
// key with null value according to GraphQL spec.
func SetStatusWithData(w http.ResponseWriter, code, msg string) {
var qr QueryResWithData
qr.Errors = append(qr.Errors, errRes{Code: code, Message: msg})
ext := make(map[string]interface{})
ext["code"] = code
qr.Errors = append(qr.Errors, GqlError{Message: msg, Extensions: ext})
// This would ensure that data key is present with value null.
if js, err := json.Marshal(qr); err == nil {
if _, err := w.Write(js); err != nil {
Expand Down

0 comments on commit 02375af

Please sign in to comment.