Skip to content

Commit 0ecae8b

Browse files
Bardhi ShtyllaAlecAivazis
Bardhi Shtylla
andauthored
Update the extensions tag to contain errors when the nautilus gateway… (#90)
* only run test coverage if there's a token * enable gomodules * no bash * Update the extensions tag to contain errors when the nautilus gateway returns an error - The “code” field is required by some frontend libraries, such as apollo-client. While this is not a graphql requirement, this is a pretty widely used pattern by libraries like graphqlgen and also by apollo-server. Co-authored-by: Alec Aivazis <alec@aivazis.com>
1 parent e529b36 commit 0ecae8b

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

http.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ type HTTPOperation struct {
2727
}
2828

2929
func formatErrors(data map[string]interface{}, err error) map[string]interface{} {
30+
return formatErrorsWithCode(data, err, "UNKNOWN_ERROR")
31+
}
32+
33+
func formatErrorsWithCode(data map[string]interface{}, err error, code string) map[string]interface{} {
3034
// the final list of formatted errors
3135
var errList graphql.ErrorList
3236

@@ -35,9 +39,7 @@ func formatErrors(data map[string]interface{}, err error) map[string]interface{}
3539
errList = list
3640
} else {
3741
errList = graphql.ErrorList{
38-
&graphql.Error{
39-
Message: err.Error(),
40-
},
42+
graphql.NewError(code, err.Error()),
4143
}
4244
}
4345

@@ -169,7 +171,10 @@ func (g *Gateway) GraphQLHandler(w http.ResponseWriter, r *http.Request) {
169171
// if there is no query or cache key
170172
if operation.Query == "" && cacheKey == "" {
171173
statusCode = http.StatusUnprocessableEntity
172-
results = append(results, formatErrors(nil, errors.New("could not find query body")))
174+
results = append(
175+
results,
176+
formatErrorsWithCode(nil, errors.New("could not find query body"), "BAD_USER_INPUT"),
177+
)
173178
continue
174179
}
175180

@@ -185,7 +190,7 @@ func (g *Gateway) GraphQLHandler(w http.ResponseWriter, r *http.Request) {
185190
// Get the plan, and return a 400 if we can't get the plan
186191
plan, err := g.GetPlans(requestContext)
187192
if err != nil {
188-
response, err := json.Marshal(formatErrors(nil, err))
193+
response, err := json.Marshal(formatErrorsWithCode(nil, err, "GRAPHQL_VALIDATION_FAILED"))
189194
if err != nil {
190195
// if we couldn't serialize the response then we're in internal error territory
191196
response, err = json.Marshal(formatErrors(nil, err))
@@ -200,7 +205,7 @@ func (g *Gateway) GraphQLHandler(w http.ResponseWriter, r *http.Request) {
200205
// fire the query with the request context passed through to execution
201206
result, err = g.Execute(requestContext, plan)
202207
if err != nil {
203-
results = append(results, formatErrors(nil, err))
208+
results = append(results, formatErrorsWithCode(nil, err, "INTERNAL_SERVER_ERROR"))
204209
continue
205210
}
206211

http_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ import (
1818
"github.com/vektah/gqlparser/ast"
1919
)
2020

21+
type resultWithErrors struct {
22+
Errors []struct {
23+
Extensions map[string]string `json:"extensions"`
24+
Message string `json:"message"`
25+
} `json:"errors"`
26+
}
27+
2128
func TestGraphQLHandler_postMissingQuery(t *testing.T) {
2229
schema, err := graphql.LoadSchema(`
2330
type Query {
@@ -83,6 +90,13 @@ func TestGraphQLHandler(t *testing.T) {
8390

8491
// make sure we got an error code
8592
assert.Equal(t, http.StatusUnprocessableEntity, responseRecorder.Result().StatusCode)
93+
94+
// verify the graphql error code
95+
result, err := readResultWithErrors(responseRecorder, t)
96+
if err != nil {
97+
assert.Error(t, err)
98+
}
99+
assert.Equal(t, result.Errors[0].Extensions["code"], "BAD_USER_INPUT")
86100
})
87101

88102
t.Run("Non-object variables fails", func(t *testing.T) {
@@ -151,9 +165,28 @@ func TestGraphQLHandler(t *testing.T) {
151165

152166
// make sure we got an error code
153167
assert.Equal(t, http.StatusInternalServerError, responseRecorder.Result().StatusCode)
168+
169+
// verify the graphql error code
170+
result, err := readResultWithErrors(responseRecorder, t)
171+
if err != nil {
172+
assert.Error(t, err)
173+
}
174+
assert.Equal(t, result.Errors[0].Extensions["code"], "UNKNOWN_ERROR")
154175
})
155176
}
156177

178+
func readResultWithErrors(responseRecorder *httptest.ResponseRecorder, t *testing.T) (*resultWithErrors, error) {
179+
body, err := ioutil.ReadAll(responseRecorder.Result().Body)
180+
if err != nil {
181+
return nil, err
182+
}
183+
184+
//result := map[string]interface{}{}
185+
result := resultWithErrors{}
186+
err = json.Unmarshal(body, &result)
187+
return &result, nil
188+
}
189+
157190
func TestQueryPlanCacheParameters_post(t *testing.T) {
158191
// load the schema we'll test
159192
schema, _ := graphql.LoadSchema(`

0 commit comments

Comments
 (0)