77 "io"
88 "io/ioutil"
99 "net/http"
10+ "net/url"
1011 "regexp"
1112 "strings"
1213
@@ -212,15 +213,23 @@ func (c Client) DirectRequest(method string, p string, params interface{}, heade
212213 url := "https://api.github.com/" + p
213214 var body io.Reader
214215 var bodyIsJSON bool
216+ isGraphQL := p == "graphql"
215217
216218 switch pp := params .(type ) {
217219 case map [string ]interface {}:
218- b , err := json .Marshal (pp )
219- if err != nil {
220- return nil , fmt .Errorf ("error serializing parameters: %w" , err )
220+ if strings .EqualFold (method , "GET" ) {
221+ url = addQuery (url , pp )
222+ } else {
223+ if isGraphQL {
224+ pp = groupGraphQLVariables (pp )
225+ }
226+ b , err := json .Marshal (pp )
227+ if err != nil {
228+ return nil , fmt .Errorf ("error serializing parameters: %w" , err )
229+ }
230+ body = bytes .NewBuffer (b )
231+ bodyIsJSON = true
221232 }
222- body = bytes .NewBuffer (b )
223- bodyIsJSON = true
224233 case io.Reader :
225234 body = pp
226235 default :
@@ -246,6 +255,55 @@ func (c Client) DirectRequest(method string, p string, params interface{}, heade
246255 return c .http .Do (req )
247256}
248257
258+ func groupGraphQLVariables (params map [string ]interface {}) map [string ]interface {} {
259+ topLevel := make (map [string ]interface {})
260+ variables := make (map [string ]interface {})
261+
262+ for key , val := range params {
263+ switch key {
264+ case "query" :
265+ topLevel [key ] = val
266+ default :
267+ variables [key ] = val
268+ }
269+ }
270+
271+ if len (variables ) > 0 {
272+ topLevel ["variables" ] = variables
273+ }
274+ return topLevel
275+ }
276+
277+ func addQuery (path string , params map [string ]interface {}) string {
278+ if len (params ) == 0 {
279+ return path
280+ }
281+
282+ query := url.Values {}
283+ for key , value := range params {
284+ switch v := value .(type ) {
285+ case string :
286+ query .Add (key , v )
287+ case []byte :
288+ query .Add (key , string (v ))
289+ case nil :
290+ query .Add (key , "" )
291+ case int :
292+ query .Add (key , fmt .Sprintf ("%d" , v ))
293+ case bool :
294+ query .Add (key , fmt .Sprintf ("%v" , v ))
295+ default :
296+ panic (fmt .Sprintf ("unknown type %v" , v ))
297+ }
298+ }
299+
300+ sep := "?"
301+ if strings .ContainsRune (path , '?' ) {
302+ sep = "&"
303+ }
304+ return path + sep + query .Encode ()
305+ }
306+
249307func handleResponse (resp * http.Response , data interface {}) error {
250308 success := resp .StatusCode >= 200 && resp .StatusCode < 300
251309
0 commit comments