...

Source file src/github.com/99designs/gqlgen/graphql/handler/transport/http_post.go

Documentation: github.com/99designs/gqlgen/graphql/handler/transport

     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, &params); 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  }
    93  

View as plain text