Skip to content

Commit

Permalink
Return full errors
Browse files Browse the repository at this point in the history
  • Loading branch information
HaraldNordgren committed Dec 3, 2024
1 parent d3e516b commit 9fd2d62
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 26 deletions.
13 changes: 12 additions & 1 deletion graphql/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,20 @@ func (c *client) MakeRequest(ctx context.Context, req *Request, resp *Response)
if err != nil {
respBody = []byte(fmt.Sprintf("<unreadable: %v>", err))
}

var gqlResp Response
if err = json.Unmarshal(respBody, &gqlResp); err != nil {
return &HTTPError{
Response: Response{
Errors: gqlerror.List{&gqlerror.Error{Message: string(respBody)}},
},
StatusCode: httpResp.StatusCode,
}
}

return &HTTPError{
Response: gqlResp,
StatusCode: httpResp.StatusCode,
Body: string(respBody),
}
}

Expand Down
62 changes: 41 additions & 21 deletions graphql/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,65 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/vektah/gqlparser/v2/gqlerror"
)

func TestMakeRequest_HTTPError(t *testing.T) {
testCases := []struct {
expectedError *HTTPError
serverResponseBody any
name string
serverResponseBody string
expectedErrorBody string
serverResponseCode int
expectedStatusCode int
}{
{
name: "400 Bad Request",
serverResponseBody: "Bad Request",
expectedErrorBody: "Bad Request",
name: "plain_text_error",
serverResponseCode: http.StatusBadRequest,
expectedStatusCode: http.StatusBadRequest,
serverResponseBody: "Bad Request",
expectedError: &HTTPError{
Response: Response{
Errors: gqlerror.List{
&gqlerror.Error{
Message: "\"Bad Request\"\n",
},
},
},
StatusCode: http.StatusBadRequest,
},
},
{
name: "429 Too Many Requests",
serverResponseBody: "Rate limit exceeded",
expectedErrorBody: "Rate limit exceeded",
name: "json_error_with_extensions",
serverResponseCode: http.StatusTooManyRequests,
expectedStatusCode: http.StatusTooManyRequests,
},
{
name: "500 Internal Server Error",
serverResponseBody: "Internal Server Error",
expectedErrorBody: "Internal Server Error",
serverResponseCode: http.StatusInternalServerError,
expectedStatusCode: http.StatusInternalServerError,
serverResponseBody: Response{
Errors: gqlerror.List{
&gqlerror.Error{
Message: "Rate limit exceeded",
Extensions: map[string]interface{}{
"code": "RATE_LIMIT_EXCEEDED",
},
},
},
},
expectedError: &HTTPError{
Response: Response{
Errors: gqlerror.List{
&gqlerror.Error{
Message: "Rate limit exceeded",
Extensions: map[string]interface{}{
"code": "RATE_LIMIT_EXCEEDED",
},
},
},
},
StatusCode: http.StatusTooManyRequests,
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(tc.serverResponseCode)
_, err := w.Write([]byte(tc.serverResponseBody))
err := json.NewEncoder(w).Encode(tc.serverResponseBody)
if err != nil {
t.Fatalf("Failed to write response: %v", err)
}
Expand All @@ -64,8 +85,7 @@ func TestMakeRequest_HTTPError(t *testing.T) {
assert.Error(t, err)
var httpErr *HTTPError
assert.True(t, errors.As(err, &httpErr), "Error should be of type *HTTPError")
assert.Equal(t, tc.expectedStatusCode, httpErr.StatusCode)
assert.Equal(t, tc.expectedErrorBody, httpErr.Body)
assert.Equal(t, tc.expectedError, httpErr)
})
}
}
Expand Down
16 changes: 12 additions & 4 deletions graphql/errors.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package graphql

import "fmt"
import (
"encoding/json"
"fmt"
)

// HTTPError represents an HTTP error with status code and response body.
// HTTPError represents an HTTP error with status coqgqde and response body.
type HTTPError struct {
Body string
Response Response
StatusCode int
}

// Error implements the error interface for HTTPError.
func (e *HTTPError) Error() string {
return fmt.Sprintf("returned error %v: '%s'", e.StatusCode, e.Body)
jsonBody, err := json.Marshal(e.Response)
if err != nil {
return fmt.Sprintf("returned error %v: '%s'", e.StatusCode, e.Response)
}

return fmt.Sprintf("returned error %v: %s", e.StatusCode, jsonBody)
}

0 comments on commit 9fd2d62

Please sign in to comment.