...
1 package transport
2
3 import (
4 "mime"
5 "net/http"
6 "net/url"
7 "strings"
8
9 "github.com/vektah/gqlparser/v2/gqlerror"
10
11 "github.com/99designs/gqlgen/graphql"
12 )
13
14
15
16
17
18 type GRAPHQL struct {
19
20
21 ResponseHeaders map[string][]string
22 }
23
24 var _ graphql.Transport = GRAPHQL{}
25
26 func (h GRAPHQL) Supports(r *http.Request) bool {
27 if r.Header.Get("Upgrade") != "" {
28 return false
29 }
30
31 mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
32 if err != nil {
33 return false
34 }
35
36 return r.Method == "POST" && mediaType == "application/graphql"
37 }
38
39 func (h GRAPHQL) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) {
40 ctx := r.Context()
41 writeHeaders(w, h.ResponseHeaders)
42 params := &graphql.RawParams{}
43 start := graphql.Now()
44 params.Headers = r.Header
45 params.ReadTime = graphql.TraceTiming{
46 Start: start,
47 End: graphql.Now(),
48 }
49
50 bodyString, err := getRequestBody(r)
51 if err != nil {
52 gqlErr := gqlerror.Errorf("could not get request body: %+v", err)
53 resp := exec.DispatchError(ctx, gqlerror.List{gqlErr})
54 writeJson(w, resp)
55 return
56 }
57
58 params.Query, err = cleanupBody(bodyString)
59 if err != nil {
60 w.WriteHeader(http.StatusUnprocessableEntity)
61 gqlErr := gqlerror.Errorf("could not cleanup body: %+v", err)
62 resp := exec.DispatchError(ctx, gqlerror.List{gqlErr})
63 writeJson(w, resp)
64 return
65 }
66
67 rc, OpErr := exec.CreateOperationContext(ctx, params)
68 if OpErr != nil {
69 w.WriteHeader(statusFor(OpErr))
70 resp := exec.DispatchError(graphql.WithOperationContext(ctx, rc), OpErr)
71 writeJson(w, resp)
72 return
73 }
74
75 var responses graphql.ResponseHandler
76 responses, ctx = exec.DispatchOperation(ctx, rc)
77 writeJson(w, responses(ctx))
78 }
79
80
81
82 func cleanupBody(body string) (out string, err error) {
83
84
85 body = strings.TrimPrefix(body, "query=")
86
87
88
89 if strings.HasPrefix(body, "%7B") {
90 body, err = url.QueryUnescape(body)
91
92 if err != nil {
93 return body, err
94 }
95 }
96
97 return body, err
98 }
99
View as plain text