This repository has been archived by the owner on Dec 11, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gql.go
92 lines (85 loc) · 2.68 KB
/
gql.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Package / library or rather wrapper for GraphQL queries execution in the painless way.
// Using it is as easy as copy / paste the query itself and set appropriate variables in.
//
// Library supports basic error reporting on unsuccessful queries and setting appropriate headers.
package gql
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"os"
"github.com/lukaszraczylo/pandati"
"github.com/tidwall/gjson"
"github.com/valyala/fasthttp"
)
// Endpoint of your GraphQL server to query
// this variable can be overwritten by setting env variable, for example:
// GRAPHQL_ENDPOINT=http://hasura.local/v1/graphql
var GraphQLUrl string
type requestBase struct {
Query string `json:"query"`
Variables interface{} `json:"variables"`
}
func prepare() {
value, present := os.LookupEnv("GRAPHQL_ENDPOINT")
if present {
GraphQLUrl = value
} else if !present && pandati.IsZero(GraphQLUrl) {
GraphQLUrl = "http://127.0.0.1:9090/v1/graphql"
fmt.Println("Setting default endpoint", GraphQLUrl)
} else {
fmt.Println("GraphQL endpoint not set.")
}
}
// queryBuilder takes query data (string) and variables (interface) as a parameter and assembles
// graphQL query. It also compacts the JSON result. Function returns query as []byte and error if anything went wrong.
func queryBuilder(data string, variables interface{}) ([]byte, error) {
var err error
var qb = &requestBase{
Query: data,
Variables: variables,
}
j := new(bytes.Buffer)
j2, err := json.Marshal(qb)
if err != nil {
return []byte{}, err
}
if err = json.Compact(j, j2); err != nil {
return []byte{}, err
}
return j.Bytes(), err
}
// Query allows you to execute the GraphQL query.
// Query is a string ( copy paste from Hasura or any other query builder )
// Variables and Headers are maps of strings ( see the example )
// Function returns whatever specified query returns and/or error.
func Query(query string, variables interface{}, headers map[string]interface{}) (string, error) {
prepare()
var err error
readyQuery, err := queryBuilder(query, variables)
if err != nil {
return "", err
}
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
req.Header.SetContentType("application/json")
for header, value := range headers {
req.Header.Add(fmt.Sprintf("%v", header), fmt.Sprintf("%v", value))
}
req.Header.SetMethod("POST")
req.SetBody(readyQuery)
req.SetRequestURI(GraphQLUrl)
res := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(res)
if err := fasthttp.Do(req, res); err != nil {
return "", err
}
body := res.Body()
toReturn := gjson.Get(string(body), "data")
if toReturn.String() == "" {
err = errors.New(string(body))
return "", err
}
return toReturn.String(), err
}