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