Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POSTing GraphQL Mutations? #154

Closed
TimBMK opened this issue Feb 9, 2021 · 4 comments
Closed

POSTing GraphQL Mutations? #154

TimBMK opened this issue Feb 9, 2021 · 4 comments

Comments

@TimBMK
Copy link

TimBMK commented Feb 9, 2021

I'm running into some trouble trying to utilize crul to send a mutation to graphQL. Specifically, I'm trying to send one that'll log me into graphQL, providing a token for all further requests (to be made with ghql - great package!).

The problem is that I can't seem to figure out how to get the format for HttpClient$post right. The curl request is as follows:
curl -g -X POST -H "Content-Type: application/json" --data "{\"query\":\"mutation($email:String!, $password:String!) { login(input:{email:$email, password:$password}) { token } }\", \"variables\": {\"email\": \"email\", \"password\": \"password\" } }" http://127.0.0.1:5001/graphql

However, when trying to put that into the crul function, I keep getting "bad request" replies from the server. I've tried dumping the whole query into the function:

link <- "http://127.0.0.1:5001/graphql"

client <- HttpClient$new(link)

client$post(encode = "json", query = "{\"query\": \"mutation($email:String!, $password:String!) { login(input: {email:$email, password:$password}) { token } }\", \"variables\": \"{ \"email\": \"email\", \"password\": \"password\" } }")

But I've also tried to get the list format right by nesting everything into lists:

client$post(query = list(
  query = list(mutation = list(email ="String!", password = "String!"), login = list(input = list(email = "$email", password = "$password")), token = NULL),
  variables = list(email = "email", password = "password")

Neither work, and I'm not sure what the correct way here is. I'm especially unsure about the format of the graphQL mutation, and how to put that into the format expected by crul. For example, how do I specify that I want the 'token' as a result via a list? And is nesting the list like this the right way to do it? Since graphQL queries are nested, I've tried reconstructing it in the query via the nested lists, but maybe that's not the way to go?

Lastly, I've also tried posting the query as body rather than query, since that may be what GraphQL is actually expecting. That didn't work, either, partly because crul throws an error of "Unsupported value type for form field 'query'" when leaving it undefined. Is there some way to only post a body?

So, kinda lost here and any help in getting the above curl call into a proper crul call would be very much appreciated!

@sckott
Copy link
Collaborator

sckott commented Feb 9, 2021

Does this work:

First, do this https://graphql.org/graphql-js/running-an-express-graphql-server/

Then:

library(crul)
con <- HttpClient$new("http://localhost:4000/graphql", headers=list(`Content-Type`="application/json"))
res <- con$post(body = '{"query": "{hello}"}', encode="json")
res$parse("UTF-8")
#> [1] "{\"data\":{\"hello\":\"Hello world!\"}}"

@TimBMK
Copy link
Author

TimBMK commented Feb 11, 2021

I've tried some simple queries on the server, and if a token is provided in the header, they all work, e.g.

client <- HttpClient$new(link, headers=list(`Content-Type`="application/json"))
client$post(body = "{\"query\": \"{ newsArticles { totalCount } }\"}", encode = "json")

gives me a 200 even without authorization in the header, the correct data when authorized.

While testing out some queries, I found out that strings in graphQL need somewhat of a different escape to not throw a'bad request' error, e.g. here (note the triple \ ):

client$post(body = "{\"query\": \"{ newsArticle(id: \\\"101\\\") { id } }\"}", encode = "json") 

However, this does not resolve the issue I'm having with the mutation. I've also tried a somewhat simplified call (even though the above curl call works in cmd), resembling the graphQL muation more closely.

The graphQL mutation is, in graphQL syntax:

mutation MyMutation {
  login(input: {email: "email", password: "password"}) {
    token
  }
}

which I made into:

client$post(body = "{\"mutation\": \"{ login(input: { email: \\\"email\\\", password: \\\"password\\\" }) { token } }\" }", encode = "json")

This gives me the same error ('400 Bad Request') as the above queries, no matter how I escape the strings "password" and "email". I've also tried the longer query with specially escaped characters, encoded as json, but with the same results.

Since standard queries work, I'm thinking it might have to do something with the mutation, but I'm not sure what the issue is here.

@TimBMK
Copy link
Author

TimBMK commented Feb 11, 2021

I've figured out my mistake. GraphQL seems to expect that a query is called as a mutation only if specifid within the query, while http is expecting the query field. Standard queries do not require this specification, however. Hence

client$post(body = "{\"query\": \"mutation { login(input: { email: \\\"email\\\", password: \\\"password\\\" }) { token } }\" }", encode = "json")

is the way to go.

Thanks for looking into it. I hope somebody will find this toubleshooting useful!

@TimBMK TimBMK closed this as completed Feb 11, 2021
@sckott
Copy link
Collaborator

sckott commented Feb 19, 2021

Nice work, thanks for sharing the solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants