42

After referring this guide I needed to access the github graphql by using curl for a testing purpose. I tried this simple command

curl -i -H "Authorization: bearer myGithubAccessToken" -X POST -d '{"query": "query {repository(owner: "wso2", name: "product-is") {description}}"}' https://api.github.com/graphql

but it gives me

problems parsing JSON

what I am doing wrong. I spent nearly 2 hours trying to figure it and tried different examples but none of them worked. Can you please be kind enough help me resolve this

Kasun Siyambalapitiya
  • 3,956
  • 8
  • 38
  • 58

4 Answers4

47

You just need to escape the double quotes that are inside the JSON as the query

$ curl -i -H 'Content-Type: application/json' -H "Authorization: bearer myGithubAccessToken" -X POST -d '{"query": "query {repository(owner: \"wso2\", name: \"product-is\") {description}}"}' https://api.github.com/graphql

Marco Daniel
  • 5,467
  • 5
  • 28
  • 36
Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
  • 4
    I came to this answer trying to access my own Django/Graphene based API; for that, I needed an extra `-H 'Content-Type: application/json'` – Silly Freak Sep 11 '17 at 08:51
34

If you want your queries to stay nice and multiline, you may do like this:

script='query {
  repositoryOwner(login:\"danbst\") {
    repositories(first: 100) {
      edges {
        node {
          nameWithOwner
          pullRequests(last: 100, states: OPEN) {
            edges {
              node {
                title
                url
                author {
                  login
                }
                labels(first: 20) {
                  edges {
                    node {
                      name
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}'
script="$(echo $script)"   # the query should be a one-liner, without newlines

curl -i -H 'Content-Type: application/json' \
   -H "Authorization: bearer ........." \
   -X POST -d "{ \"query\": \"$script\"}" https://api.github.com/graphql
mbomb007
  • 3,788
  • 3
  • 39
  • 68
danbst
  • 3,363
  • 18
  • 38
  • Why one needs `script="$(echo $script)"`? – dkrikun Dec 20 '18 at 18:26
  • @dkrikun To remove newlines. As of time of writing newlines were not allowed in request body. `sed` solution would work here as well – danbst Dec 22 '18 at 14:46
  • 1
    it looks like newlines are now allowed, I've got them in my JSON (similar to the structure the explorer uses) and as long as the quotes are escaped, it works perfectly – Lorna Mitchell Dec 24 '19 at 12:26
  • I updated the solution to avoid escaping quotes, by using sed to do it. – Denis Rouzaud Feb 06 '20 at 05:55
  • 8
    Or you could just use `curl -H "Authorization: token YOUR_GITHUB_TOKEN" -X POST https://api.github.com/graphql --data @gql.json` with a file named `gql.json` having your object, where you can easily make changes with your favorite code editor with json formatter, etc. – Jerry Green Oct 19 '20 at 18:05
  • `script="$(echo $script)"` is unnecessarily obscure, and shellcheck and friends will complain about the bare `$script` without double quotes around it. I use `script=$(echo "$script" | tr -d '\n')`, which is clear about what it does. – APerson Jul 28 '23 at 01:09
6

I recommend storing the graphql in one file, and script for processing it in a separate file, and then combining the two at the prompt.

This lets you use graphql syntax highlighting plugins and graphql pretty printers while editing examplequery.gql in your favorite editor. While also preserving the ability to make use of your cli toolkit for cases where your graphql-fu isn't up to the task.

Usage:

❯ ./ghgql.sh examplequery.gql

    {"data":{"user":{"repositories":{"nodes":[{"name":"firstrepo","languages":{"nodes":[]}},{"name":"secondrepo","languages":{"nodes":[{"name":"Shell"},{"name":"Vim script"}]}},{"name":"thirdrepo","languages":{"nodes":[{"name":"TeX"}]}}]}}}}

❯ ./ghgql.sh examplequery.gql \
    | jq -c '.data.user.repositories.nodes | to_entries | .[]' \
    | grep 'TeX' \
    | jq -r '.value.name'

    thirdrepo

ghgql.sh

#!/usr/bin/env bash

if [ ! -f $1 ] || [ $# -ne 1 ]
then
    echo Queries the github graphql API
    echo "Usage:"
    echo
    echo "$0 somefile.gql"
fi

# read the gql query from the file named in the argument
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
TOKEN=$(cat $DIR/token)
QUERY=$(jq -n \
           --arg q "$(cat $1 | tr -d '\n')" \
           '{ query: $q }')

# do the query
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: bearer $TOKEN" \
  --data "$QUERY" \
  https://api.github.com/graphql

examplequery.gql

{
  user(login: "MatrixManAtYrService") {
    repositories(first: 3) {
      nodes {
        name
        languages(first: 3) {
          nodes {
            name
          }
        }
      }
    }
  }
}
MatrixManAtYrService
  • 8,023
  • 1
  • 50
  • 61
  • I change bearer to my GitHub user name and place a PAT from GitHub in a file named token in the working directory, but still get `{ "message": "This endpoint requires you to be authenticated.", "documentation_url": "https://docs.github.com/graphql/guides/forming-calls-with-graphql#authenticating-with-graphql" }` Am I not understanding the way token is intended to be passed? – robartsd Dec 23 '21 at 03:53
  • @robartsd the word `bearer` is not the name of a GitHub user. So you should keep it at `bearer`. I think it indicates a GitHub personal access token is comming. A working syntax could be: `-H "Authorization: bearer somegithubpersonalaccesstoken" \`. – a.t. Feb 28 '22 at 18:29
  • THANK YOU! underrated answer imo. This is so much easier to focus on the graphql query itself without messing up with the json formatting – Tom Apr 18 '23 at 10:49
6

Since this is the first hit for 'graphql curl', here's a simple example:

$ curl \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"query": "query { fish(key:\"838\") { name } }"}' \
  http://localhost:4001

{"data":{"fish":{"name":"plecy"}}}
Brian Burns
  • 20,575
  • 8
  • 83
  • 77