I cannot seem to get variables in a graphql query made with apollo into the query body to be accepted into backend server.
I have a simple vue frontend and go backend. In a vue-component I have the following query:
apollo: {
entry: {
query: gql`
query variables($userID: Int){
entries(userID: $userID) {
id,
value,
timeStamp
}
}
`,
variables() {
return {
userID: 2
}
},
update: data => data,
}
}
}
On my go backend I nave the handler function for all POST requests
// GraphQL returns an http.HandlerFunc for our /graphql endpoint
func (s *Server) GraphQL() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
//Allow CORS here By * or specific origin
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
// Check to ensure query was provided in the request body
if r.Body == nil {
http.Error(w, "Must provide graphql query in request body", 400)
return
}
var rBody reqBody
// Decode the request body into rBody
err := json.NewDecoder(r.Body).Decode(&rBody)
if err != nil {
http.Error(w, "Error parsing JSON request body", 400)
}
fmt.Println(rBody.Query)
// Execute graphql query
result := gql.ExecuteQuery(rBody.Query, *s.GqlSchema)
// render.JSON comes from the chi/render package and handles
// marshalling to json, automatically escaping HTML and setting
// the Content-Type as application/json.
render.JSON(w, r, result)
}
}
When I run the query, I am returned {"entries" : null}. When I print out the query that was sent to my go server, I get the following:
query variables($userID: Int) {
entries(userID: $userID) {
id
value
timeStamp
__typename
}
}
In line 2 of this I would hope to see entries(userID: 2). Indeed, if I remove the variables from my query made in vue, and hardcode the userID in the query, everything works.
I checked to make sure the variable is being sent in someway, which if I look at the POST request made it has the following in the parameters:
operationName variables
query query variables($userID: Int) { entries(userID: $userID) { id value timeStamp __typename } }
variables {…}
userID 2
Am I not accepting the data correctly on my backend, as the variable userID is being sent in the POST request?
Solution: Thanks to @cgcgbcbc for the solution. My reqBody
struct was the following:
type reqBody struct {
Query string `json:"query"`
}
When it should be:
type reqBody struct {
Query string `json:"query"`
Variables map[string]interface{} `json:"variables"`
}
Then I just needed to pass rBody.Variables
to my ExecuteQuery
function as in his solution.
For your question, the data receiving in your backend is correct, the query itself does not contain the query parameter, the query parameter is sent via variables
key.
The response issue is this line result := gql.ExecuteQuery(rBody.Query, *s.GqlSchema)
.
variables
from the request body need also be passed to ExecuteQuery
. An example implementation using graphql-go/graphql
Do
function can be
func executeQuery(query string, schema graphql.Schema, variables map[string]interface{}) *graphql.Result {
result := graphql.Do(graphql.Params{
Schema: schema,
RequestString: query,
VariableValues: variables
})
if len(result.Errors) > 0 {
fmt.Printf("errors: %v", result.Errors)
}
return result
}
And an example of type reqBody
can be
type reqBody struct {
Query string
Variables map[string]interface{}
}
Then json.NewDecoder(r.Body).Decode(&rBody)
will automatically set Query and Variables