How to call a GraphQL endpoint with plain HTTP
If you work with a GraphQL application you may be accustomed to using a specialized interface or framework such as GraphiQL or Relay. But you can use plain Web requests too.
GraphQL vs REST
In a Web application using GraphQL you work with a special query language with with main methods being query
and mutation
, whereas in a more conventional REST style Web application, you work with “plain” HTTP methods such as GET
, POST
, PATCH
, DELETE
.
It might seem that these two approaches are worlds apart, but under the hood, GraphQL queries are themselves sent over HTTP (GraphQL servers typically handle GET
and POST
requests).
So, if you have a means for constructing a plain HTTP request, and if you know how to transmit your query within it, you can work with a GraphQL server using plain HTTP.
GraphQL over HTTP
A typical GraphQL server would handle requests such as:
GET
requests, where the query is passed in via the URL- e.g.
http://example.com/graphql?query={user{name}}
- e.g.
POST
requests ofapplication/json
content type where the query is passed in via the JSON body- e.g.
{ "query": "...", "variables": { "fruit": "apple", ... }
- e.g.
So, the task then is to pass your desired GraphQL query (as a valid JSON string) using the query
field of the JSON body, and, if your query uses variables, to pass your dictionary of variables using the variables
field.
Here’s an example GraphQL query with variables as a POST request, in the command-line via cURL:
curl --request POST \ --url 'https://api.example.app/graphql' \ --header 'Content-Type: application/json' \ --data-raw '{ "query":"mutation($id: Int!) { createUser(userId: $id) { id } }", "variables": { "id": 123 } }'
⚠️ The
query
field in the JSON body needs to be a valid JSON string. That means, unfortunately, that it cannot contain newlines, and also means that you need to escape double-quote characters. So, if you have an existing GraphQL query that you want to put into the HTTP request, you’ll need to “flatten” it into one line and escape double-quotes.
Here’s a few good references to read further:
- GraphQL docs
- Serving over HTTP (with more detail on
GET
andPOST
requests to a GraphQL server) - GraphQL Clients (with example queries via
curl
on the command line andfetch
from a browser)
- Serving over HTTP (with more detail on
- Apollo blog
- Contentful blog
- Other
Backstory: Basedash Actions
Actions give you the ability to build and run predefined Web requests using Basedash. You can define an Action to target a given endpoint (on your own server, or a third-party server) and execute a Web request with user-provided parameters. You can read all about it here in our documentation: https://docs.basedash.com/actions.
When you’re building an Action, you’re essentially defining the recipe for an HTTP request. You specify the HTTP method, the URL, the headers and the body. While we don’t yet offer any special GraphQL affordances in our Action builder, it’s entirely possible to build Actions which target a GraphQL endpoint. While it might not be quite so ergonomic to fit your query into the request body of your Action, it should be functional.
Working with variables
If you want to setup an Action in Basedash which executes a GraphQL query, you have a few options when it comes to working with variables for passing in arguments. Keep in mind, there’s two levels at play:
- Arguments supplied by the user who runs an Action (which get resolved in the request body of the Action)
- Basedash uses double-curly bracket delimiters for variables, e.g.
{{ userName }}
- Basedash uses double-curly bracket delimiters for variables, e.g.
- Arguments supplied by the
variables
field of the request body (which get resolved in the GraphQL query)- GraphQL uses a dollar-sign sigil for variables, e.g.
$userName
- GraphQL uses a dollar-sign sigil for variables, e.g.
So, there’s variables for your Action, that can be used in the GraphQL query directly, or can be used in the GraphQL variables, which are in turn passed to the query.
Example Action: Assigning credits to a user
Imagine you have a GraphQL server with a mutation
for assigning credits to a user, and you want to setup an Action in Basedash so it’s handy for your teammates to use. You want to set it up so that when they run it they’d supply a user’s email and a number of credits to make it happen.
- For starters, your action would use the
POST
HTTP method, and you’d ensure there’s a header ofContent-Type: application/json
- Your action would have the following inputs:
- Email: (with the identifier
email
) - Number of credits: (with the identifier
numberOfCredits
)
- Email: (with the identifier
- But when it comes to defining the body, you have a few options:
-
Interpolate the Action Inputs directly into the
query
(not making use of GraphQL variables) e.g.{ "query": "mutation { addCredits(email: \"{{ email }}\", qty: \"{{ numberOfCredits }}\") { credits } }" }
-
Make use of GraphQL variables and interpolate the Action Inputs into the values in the
variables
object, e.g.{ "query": "mutation($email: String!, $quantity: Int!) { addCredits(email: $email, qty: $quantity) { credits } }", "variables": { "email": "{{ email }}", "quantity": "{{ numberOfCredits }}" } }
-
You can also do a bit of both. You can define a variables
field in the request field and interpolate Action inputs into it, at the same time as interpolating Action inputs into the query
field. (Recall, anywhere in the body where you have a double-curly-bracket delimited variable such as {{ email }}
, it will be interpolated).
Which one do you find cleaner? Which one might be better for your needs? Part of it is just personal preference.
However, if you do setup and use a variables
field in the body, then you do potentially get some extra benefits:
- You might avoid having to use escape character sequences.
- If you’re running the Action against your own GraphQL server, things may be easier to log and monitor with the benefit of having things parameterized.
- You can leverage the typechecking of GraphQL variables.
- Currently Action Inputs in Basedash don’t support any kind of typechecking, so
numberOfCredits
can’t be ensured to be an integer. But when it’s routed through the$quantity: Int!
argument, then GraphQL does ensure it’s an integer.
- Currently Action Inputs in Basedash don’t support any kind of typechecking, so
Here’s a few references:
- Passing Arguments (GraphQL docs) (good explanation of variables in GraphQL, with some examples)
- GraphQL Variables (Dgraph Docs) (nice example with nested variables)
Example Action: Create an issue in Linear
At Basedash we use Linear as our issue tracking tool. When developing our Action feature set we created a handful of sample Actions for use for development and testing internally. One such sample Action we made targets the Linear GraphQL API and executes a mutation to create a new issue. Here’s a screenshot of how it looks:
And here’s the JSON body we used:
{ "query":"mutation($title: String! $description: String! $assigneeId: String! $teamId: String!) { issueCreate( input: { title: $title description: $description assigneeId: $assigneeId teamId: $teamId }) { success issue { id title } } }", "variables": { "title": "{{ issueName }}", "description": "{{ description }}", "assigneeId": "1234abcd-not-a-real-user-id-56789", "teamId": "1234abcd-not-a-real-team-id-56789" } }
Some things to note:
- The
query
field of the JSON body needs to be a single line with escaped double-quotes. - The Action takes the inputs
issueName
anddescription
and results in a Linear issue being created with those values. - The GraphQL query also takes an
assigneeId
and ateamID
, and those are baked into the body itself (not interpolated in). One possible way to make this more sophisticated would be to define an Action input so the user who runs the Action can provide anassigneeId
. - This Action’s body defines both
query
and avariables
fields (recall a few of the advantages to setting things up this way as described in the above example for assigning credits to a user)
References:
Conclusion
Down the road we plan to add more special-purpose functionality for building GraphQL type Actions. The biggest pain-point at the moment is having to “flatten” the query into a single-line JSON string with escaped double quotes. Among other things, we plan to build out a suitable query editor and related UI, so things don’t have to get crammed into the plain HTTP body.
Still, Basedash Actions can be used as they currently are to target GraphQL endpoints, and it should be perfectly functional.
Invite only
We're building the next generation of data visualization.
How to Center a Table in HTML with CSS
Jeremy Sarchet
Adjusting HTML Table Column Width for Better Design
Robert Cooper
How to Link Multiple CSS Stylesheets in HTML
Robert Cooper
Mastering HTML Table Inline Styling: A Guide
Max Musing
HTML Multiple Style Attributes: A Quick Guide
Max Musing
How to Set HTML Table Width for Responsive Design
Max Musing