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