github.com/99designs/gqlgen@v0.17.45/graphql/handler/transport/http_post.go (about) 1 package transport 2 3 import ( 4 "fmt" 5 "io" 6 "mime" 7 "net/http" 8 "strings" 9 10 "github.com/vektah/gqlparser/v2/gqlerror" 11 12 "github.com/99designs/gqlgen/graphql" 13 ) 14 15 // POST implements the POST side of the default HTTP transport 16 // defined in https://github.com/APIs-guru/graphql-over-http#post 17 type POST struct { 18 // Map of all headers that are added to graphql response. If not 19 // set, only one header: Content-Type: application/json will be set. 20 ResponseHeaders map[string][]string 21 } 22 23 var _ graphql.Transport = POST{} 24 25 func (h POST) Supports(r *http.Request) bool { 26 if r.Header.Get("Upgrade") != "" { 27 return false 28 } 29 30 mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) 31 if err != nil { 32 return false 33 } 34 35 return r.Method == "POST" && mediaType == "application/json" 36 } 37 38 func getRequestBody(r *http.Request) (string, error) { 39 if r == nil || r.Body == nil { 40 return "", nil 41 } 42 body, err := io.ReadAll(r.Body) 43 if err != nil { 44 return "", fmt.Errorf("unable to get Request Body %w", err) 45 } 46 return string(body), nil 47 } 48 49 func (h POST) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) { 50 ctx := r.Context() 51 writeHeaders(w, h.ResponseHeaders) 52 params := &graphql.RawParams{} 53 start := graphql.Now() 54 params.Headers = r.Header 55 params.ReadTime = graphql.TraceTiming{ 56 Start: start, 57 End: graphql.Now(), 58 } 59 60 bodyString, err := getRequestBody(r) 61 if err != nil { 62 gqlErr := gqlerror.Errorf("could not get json request body: %+v", err) 63 resp := exec.DispatchError(ctx, gqlerror.List{gqlErr}) 64 writeJson(w, resp) 65 return 66 } 67 68 bodyReader := io.NopCloser(strings.NewReader(bodyString)) 69 if err = jsonDecode(bodyReader, ¶ms); err != nil { 70 w.WriteHeader(http.StatusBadRequest) 71 gqlErr := gqlerror.Errorf( 72 "json request body could not be decoded: %+v body:%s", 73 err, 74 bodyString, 75 ) 76 resp := exec.DispatchError(ctx, gqlerror.List{gqlErr}) 77 writeJson(w, resp) 78 return 79 } 80 81 rc, OpErr := exec.CreateOperationContext(ctx, params) 82 if OpErr != nil { 83 w.WriteHeader(statusFor(OpErr)) 84 resp := exec.DispatchError(graphql.WithOperationContext(ctx, rc), OpErr) 85 writeJson(w, resp) 86 return 87 } 88 89 var responses graphql.ResponseHandler 90 responses, ctx = exec.DispatchOperation(ctx, rc) 91 writeJson(w, responses(ctx)) 92 }