From 42e110453498b2690ce4412b384881a3bf55d0c5 Mon Sep 17 00:00:00 2001 From: Artyom Blagov Date: Thu, 4 Oct 2018 12:21:38 +0300 Subject: [PATCH 1/2] reverse errors and data order in response --- graphql/response.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/graphql/response.go b/graphql/response.go index 927fabede6d..6fe55d56dc4 100644 --- a/graphql/response.go +++ b/graphql/response.go @@ -8,9 +8,12 @@ import ( "github.com/vektah/gqlparser/gqlerror" ) +// Errors are intentionally serialized first based on the advice in +// https://github.com/facebook/graphql/commit/7b40390d48680b15cb93e02d46ac5eb249689876#diff-757cea6edf0288677a9eea4cfc801d87R107 +// and https://github.com/facebook/graphql/pull/384 type Response struct { - Data json.RawMessage `json:"data"` Errors gqlerror.List `json:"errors,omitempty"` + Data json.RawMessage `json:"data"` Extensions map[string]interface{} `json:"extensions,omitempty"` } From f1f043b9d4e97d3dc8ad1559110e8ff8688b4afe Mon Sep 17 00:00:00 2001 From: Artyom Blagov Date: Mon, 15 Oct 2018 10:13:09 +0300 Subject: [PATCH 2/2] reverse 'data' and 'error' fields order in failure tests --- handler/graphql_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/handler/graphql_test.go b/handler/graphql_test.go index aa60f4a2f61..8dff6c182ed 100644 --- a/handler/graphql_test.go +++ b/handler/graphql_test.go @@ -45,31 +45,31 @@ func TestHandlerPOST(t *testing.T) { t.Run("decode failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", "notjson") assert.Equal(t, http.StatusBadRequest, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}],"data":null}`, resp.Body.String()) }) t.Run("parse failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}],"data":null}`, resp.Body.String()) }) t.Run("validation failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "{ me { title }}"}`) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"Cannot query field \"title\" on type \"User\".","locations":[{"line":1,"column":8}]}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"Cannot query field \"title\" on type \"User\".","locations":[{"line":1,"column":8}]}],"data":null}`, resp.Body.String()) }) t.Run("invalid variable", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "query($id:Int!){user(id:$id){name}}","variables":{"id":false}}`) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}],"data":null}`, resp.Body.String()) }) t.Run("execution failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "mutation { me { name } }"}`) assert.Equal(t, http.StatusOK, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"mutations are not supported"}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String()) }) } @@ -85,25 +85,25 @@ func TestHandlerGET(t *testing.T) { t.Run("decode failure", func(t *testing.T) { resp := doRequest(h, "GET", "/graphql?query=me{id}&variables=notjson", "") assert.Equal(t, http.StatusBadRequest, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"variables could not be decoded"}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"variables could not be decoded"}],"data":null}`, resp.Body.String()) }) t.Run("invalid variable", func(t *testing.T) { resp := doRequest(h, "GET", `/graphql?query=query($id:Int!){user(id:$id){name}}&variables={"id":false}`, "") assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}],"data":null}`, resp.Body.String()) }) t.Run("parse failure", func(t *testing.T) { resp := doRequest(h, "GET", "/graphql?query=!", "") assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}],"data":null}`, resp.Body.String()) }) t.Run("no mutations", func(t *testing.T) { resp := doRequest(h, "GET", "/graphql?query=mutation{me{name}}", "") assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"GET requests only allow query operations"}]}`, resp.Body.String()) + assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String()) }) }