Skip to content

Commit

Permalink
fix: safe http error response (#2438)
Browse files Browse the repository at this point in the history
* safe http error when parsing body

* fix tests

* fix linting

* fix linting

* Dispatch decoding errors so hook can present them

Signed-off-by: Steve Coffman <steve@khanacademy.org>

* Revert test expectation to original

Signed-off-by: Steve Coffman <steve@khanacademy.org>

Signed-off-by: Steve Coffman <steve@khanacademy.org>
Co-authored-by: Steve Coffman <steve@khanacademy.org>
  • Loading branch information
koniuszy and StevenACoffman committed Dec 3, 2022
1 parent 86c144f commit 463d213
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 20 deletions.
60 changes: 47 additions & 13 deletions graphql/handler/transport/http_post.go
@@ -1,8 +1,14 @@
package transport

import (
"fmt"
"io"
"log"
"mime"
"net/http"
"strings"

"github.com/vektah/gqlparser/v2/gqlerror"

"github.com/99designs/gqlgen/graphql"
)
Expand All @@ -26,31 +32,59 @@ func (h POST) Supports(r *http.Request) bool {
return r.Method == "POST" && mediaType == "application/json"
}

func getRequestBody(r *http.Request) (string, error) {
if r == nil || r.Body == nil {
return "", nil
}
body, err := io.ReadAll(r.Body)
if err != nil {
return "", fmt.Errorf("unable to get Request Body %w", err)
}
return string(body), nil
}

func (h POST) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) {
ctx := r.Context()
w.Header().Set("Content-Type", "application/json")

var params *graphql.RawParams
params := &graphql.RawParams{}
start := graphql.Now()
if err := jsonDecode(r.Body, &params); err != nil {
w.WriteHeader(http.StatusBadRequest)
writeJsonErrorf(w, "json body could not be decoded: "+err.Error())
return
}

params.Headers = r.Header

params.ReadTime = graphql.TraceTiming{
Start: start,
End: graphql.Now(),
}

rc, err := exec.CreateOperationContext(r.Context(), params)
bodyString, err := getRequestBody(r)
if err != nil {
w.WriteHeader(statusFor(err))
resp := exec.DispatchError(graphql.WithOperationContext(r.Context(), rc), err)
gqlErr := gqlerror.Errorf("could not get json request body: %+v", err)
resp := exec.DispatchError(ctx, gqlerror.List{gqlErr})
log.Printf("could not get json request body: %+v", err.Error())
writeJson(w, resp)
}

bodyReader := io.NopCloser(strings.NewReader(bodyString))
if err = jsonDecode(bodyReader, &params); err != nil {
w.WriteHeader(http.StatusBadRequest)
gqlErr := gqlerror.Errorf(
"json request body could not be decoded: %+v body:%s",
err,
bodyString,
)
resp := exec.DispatchError(ctx, gqlerror.List{gqlErr})
log.Printf("decoding error: %+v body:%s", err.Error(), bodyString)
writeJson(w, resp)
return
}
responses, ctx := exec.DispatchOperation(r.Context(), rc)

rc, OpErr := exec.CreateOperationContext(ctx, params)
if OpErr != nil {
w.WriteHeader(statusFor(OpErr))
resp := exec.DispatchError(graphql.WithOperationContext(ctx, rc), OpErr)
writeJson(w, resp)
return
}

var responses graphql.ResponseHandler
responses, ctx = exec.DispatchOperation(ctx, rc)
writeJson(w, responses(ctx))
}
2 changes: 1 addition & 1 deletion graphql/handler/transport/http_post_test.go
Expand Up @@ -26,7 +26,7 @@ func TestPOST(t *testing.T) {
resp := doRequest(h, "POST", "/graphql", "notjson")
assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
assert.Equal(t, `{"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}],"data":null}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"json request body could not be decoded: invalid character 'o' in literal null (expecting 'u') body:notjson"}],"data":null}`, resp.Body.String())
})

t.Run("parse failure", func(t *testing.T) {
Expand Down
7 changes: 4 additions & 3 deletions plugin/resolvergen/testdata/filetemplate/out/schema.custom.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 463d213

Please sign in to comment.