Skip to content

Commit f4e34c4

Browse files
authored
Merge pull request #5 from RuntimeRacer/hotfix-kajitool-handler
Added additional handling around Invalid Error field response
2 parents 1fcea6a + 49e937e commit f4e34c4

File tree

1 file changed

+86
-10
lines changed

1 file changed

+86
-10
lines changed

graphql.go

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8-
"github.com/runtimeracer/go-graphql-client/internal/jsonutil"
8+
"io"
99
"io/ioutil"
1010
"net/http"
1111
"strings"
1212

1313
"golang.org/x/net/context/ctxhttp"
14+
15+
"github.com/runtimeracer/go-graphql-client/internal/jsonutil"
1416
)
1517

1618
// Client is a GraphQL client.
@@ -163,12 +165,8 @@ func (c *Client) do(ctx context.Context, op operationType, v interface{}, variab
163165
body, _ := ioutil.ReadAll(resp.Body)
164166
return fmt.Errorf("non-200 OK status code: %v body: %q", resp.Status, body)
165167
}
166-
var out struct {
167-
Data *json.RawMessage
168-
Errors errors
169-
//Extensions interface{} // Unused.
170-
}
171-
err = json.NewDecoder(resp.Body).Decode(&out)
168+
var out graphQLStdOut
169+
out, err = c.unmarshalGraphQLResult(resp.Body)
172170
if err != nil {
173171
// TODO: Consider including response body in returned error, if deemed helpful.
174172
return err
@@ -186,12 +184,49 @@ func (c *Client) do(ctx context.Context, op operationType, v interface{}, variab
186184
return nil
187185
}
188186

187+
func (c *Client) unmarshalGraphQLResult(responseBody io.Reader) (graphQLStdOut, error) {
188+
// Try unmarshal into default format
189+
var output graphQLStdOut
190+
err := json.NewDecoder(responseBody).Decode(&output)
191+
if err != nil {
192+
// TODO: Consider including response body in returned error, if deemed helpful.
193+
// TODO: Add Warning message somehow that default is not working
194+
var extFormat graphQLExtOut
195+
err := json.NewDecoder(responseBody).Decode(&extFormat)
196+
if err != nil {
197+
// Output too weird or query error
198+
return output, err
199+
}
200+
201+
// Convert Ext to default to meet criteria
202+
output = graphQLStdOut{
203+
Data: extFormat.Data,
204+
Errors: extFormat.Errors.ConvertToStandard(),
205+
Extensions: extFormat.Extensions,
206+
}
207+
}
208+
return output, nil
209+
}
210+
211+
type graphQLStdOut struct {
212+
Data *json.RawMessage
213+
Errors errors
214+
Extensions interface{}
215+
}
216+
217+
type graphQLExtOut struct {
218+
Data *json.RawMessage
219+
Errors errorsExt
220+
Extensions interface{}
221+
}
222+
189223
// errors represents the "errors" array in a response from a GraphQL server.
190224
// If returned via error interface, the slice is expected to contain at least 1 element.
191225
//
192226
// Specification: https://facebook.github.io/graphql/#sec-Errors.
193-
type errors []struct {
194-
Message []interface{}
227+
type errors []errorStruct
228+
type errorStruct struct {
229+
Message string
195230
Locations []struct {
196231
Line int
197232
Column int
@@ -200,13 +235,54 @@ type errors []struct {
200235

201236
// Error implements error interface.
202237
func (e errors) Error() string {
203-
var stringOutput = make([]string, 0)
238+
if len(e) == 0 {
239+
return ""
240+
}
241+
return e[0].Message
242+
}
243+
244+
// errorsExt represents the "errors" array in a response from a GraphQL server.
245+
// If returned via error interface, the slice is expected to contain at least 1 element.
246+
// The "Ext" variant of this struct is able to handle non-standard implementations of the error message
247+
type errorsExt []errorsExtStruct
248+
type errorsExtStruct struct {
249+
Message []interface{}
250+
Locations []struct {
251+
Line int
252+
Column int
253+
}
254+
}
255+
256+
// Error implements error interface.
257+
func (e errorsExt) Error() string {
258+
if len(e) == 0 {
259+
return ""
260+
}
261+
262+
var stringOutput = make([]string, len(e[0].Message))
204263
for i := range e[0].Message {
205264
stringOutput[i] = fmt.Sprintf("%v", e[0].Message[i])
206265
}
207266
return strings.Join(stringOutput, ";")
208267
}
209268

269+
// ConvertToStandard translates extended error structs into structs matching the GraphQL Standard
270+
func (e errorsExt) ConvertToStandard() errors {
271+
if len(e) == 0 {
272+
return nil
273+
}
274+
275+
standardError := make(errors, len(e))
276+
for i := range e[0].Message {
277+
standardError[i] = errorStruct{
278+
Message: fmt.Sprintf("%v", e[0].Message[i]),
279+
Locations: e[0].Locations,
280+
}
281+
}
282+
283+
return standardError
284+
}
285+
210286
type operationType uint8
211287

212288
const (

0 commit comments

Comments
 (0)