github.com/fortexxx/gqlgen@v0.10.3-0.20191216030626-ca5ea8b21ead/graphql/handler/transport/http_get.go (about)

     1  package transport
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"net/http"
     7  	"strings"
     8  
     9  	"github.com/99designs/gqlgen/graphql"
    10  	"github.com/vektah/gqlparser/ast"
    11  )
    12  
    13  // GET implements the GET side of the default HTTP transport
    14  // defined in https://github.com/APIs-guru/graphql-over-http#get
    15  type GET struct{}
    16  
    17  var _ graphql.Transport = GET{}
    18  
    19  func (h GET) Supports(r *http.Request) bool {
    20  	if r.Header.Get("Upgrade") != "" {
    21  		return false
    22  	}
    23  
    24  	return r.Method == "GET"
    25  }
    26  
    27  func (h GET) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) {
    28  	raw := &graphql.RawParams{
    29  		Query:         r.URL.Query().Get("query"),
    30  		OperationName: r.URL.Query().Get("operationName"),
    31  	}
    32  
    33  	if variables := r.URL.Query().Get("variables"); variables != "" {
    34  		if err := jsonDecode(strings.NewReader(variables), &raw.Variables); err != nil {
    35  			w.WriteHeader(http.StatusBadRequest)
    36  			writeJsonError(w, "variables could not be decoded")
    37  			return
    38  		}
    39  	}
    40  
    41  	if extensions := r.URL.Query().Get("extensions"); extensions != "" {
    42  		if err := jsonDecode(strings.NewReader(extensions), &raw.Extensions); err != nil {
    43  			w.WriteHeader(http.StatusBadRequest)
    44  			writeJsonError(w, "extensions could not be decoded")
    45  			return
    46  		}
    47  	}
    48  
    49  	rc, err := exec.CreateOperationContext(r.Context(), raw)
    50  	if err != nil {
    51  		w.WriteHeader(http.StatusUnprocessableEntity)
    52  		resp := exec.DispatchError(graphql.WithOperationContext(r.Context(), rc), err)
    53  		writeJson(w, resp)
    54  		return
    55  	}
    56  	op := rc.Doc.Operations.ForName(rc.OperationName)
    57  	if op.Operation != ast.Query {
    58  		w.WriteHeader(http.StatusNotAcceptable)
    59  		writeJsonError(w, "GET requests only allow query operations")
    60  		return
    61  	}
    62  
    63  	responses, ctx := exec.DispatchOperation(r.Context(), rc)
    64  	writeJson(w, responses(ctx))
    65  }
    66  
    67  func jsonDecode(r io.Reader, val interface{}) error {
    68  	dec := json.NewDecoder(r)
    69  	dec.UseNumber()
    70  	return dec.Decode(val)
    71  }