graphql/handler/transport/http_post.go (89 lines of code) (raw):

package transport import ( "bytes" "fmt" "io" "mime" "net/http" "sync" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/99designs/gqlgen/graphql" ) // POST implements the POST side of the default HTTP transport // defined in https://github.com/APIs-guru/graphql-over-http#post type POST struct { // Map of all headers that are added to graphql response. If not // set, only one header: Content-Type: application/json will be set. ResponseHeaders map[string][]string } var _ graphql.Transport = POST{} func (h POST) Supports(r *http.Request) bool { if r.Header.Get("Upgrade") != "" { return false } mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) if err != nil { return false } 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 } var pool = sync.Pool{ New: func() any { return &graphql.RawParams{} }, } func (h POST) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) { ctx := r.Context() writeHeaders(w, h.ResponseHeaders) params := pool.Get().(*graphql.RawParams) defer func() { params.Headers = nil params.ReadTime = graphql.TraceTiming{} params.Extensions = nil params.OperationName = "" params.Query = "" params.Variables = nil pool.Put(params) }() params.Headers = r.Header start := graphql.Now() params.ReadTime = graphql.TraceTiming{ Start: start, End: graphql.Now(), } bodyBytes, err := io.ReadAll(r.Body) if err != nil { gqlErr := gqlerror.Errorf("could not read request body: %+v", err) resp := exec.DispatchError(ctx, gqlerror.List{gqlErr}) writeJson(w, resp) return } bodyReader := bytes.NewReader(bodyBytes) 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, string(bodyBytes), ) resp := exec.DispatchError(ctx, gqlerror.List{gqlErr}) writeJson(w, resp) return } 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)) }