API or an Application Program Interface is a family of protocols, commands, and functions that are used to build and integrate application software. In essence, API is the intermediary that enables two applications to connect. And for years, REST API was recognized as the standard protocol for web APIs. However, there is a visible trend that could potentially upend this inclination towards REST API. The State of Javascript 2018 report finds that, out of the developers who were surveyed in 2016, only 5% used GraphQL. Whereas in 2018, the numbers rapidly increased to a massive 20.4%. Although these numbers do not represent the preference of GraphQL over REST API, this clearly indicates the significant growth in the number of developers who opt for GraphQL in web applications.
In a two-part series about GraphQL, we discuss the following topics:
- Introduction to GraphQL
- GraphQL vs. REST
- GraphQL’s declarative data fetching
- GraphQL: Common misconfigurations that enable hackers
- Testing common misconfigurations in GraphQL
In this part, we explore:
- What is GraphQL?
- How to identify a GraphQL instance?
- How to configure the GraphQL server?
- Root types of GraphQL schema
- GraphQL vs. REST (focused on data fetching)
- GraphQL: Smooth, declarative data fetching
Introduction to GraphQL
What is GraphQL?
It is an open source query language for APIs that helps to load data from a server to the client in a much simpler way. Unlike REST APIs, GraphQL APIs are arranged as types and fields and not as endpoints. This feature ensures that applications can request for only what can be obtained to provide clear responses. GraphQL API fetches the exact data requested; nothing less, nothing more.
It was developed by Facebook in 2012 and was later publicly released in 2015. Today, GraphQL is rapidly adopted by clients, big and small, from all over the world. Prominent websites and mobile apps such as Facebook, Twitter, GitHub, Pinterest, Airbnb, etc. use GraphQL.
REST API suffers from the lack of a robust API documentation making it difficult for developers to know the specific operations that the API supports and how to use them efficiently. But the GraphQL schema properly defines its operations, input values, and possible outcomes. When a client sends a query request, GraphQL’s resolver function fetches the result from the source.
GraphQL allows frontend developers to retrieve data from the backend with unparalleled ease, which explains why it is generally described as Frontend Directed API technology. Evidently, it is more efficient, powerful, and flexible, and is a better alternative to REST API.
How to identify a GraphQL instance?
- A GraphQL HTTP request is typically sent to the following endpoints:
- /graphql
- /graphql/console
- /graphiql
- The GraphQL request looks similar to JSON but it’s different, as seen in the following request:
While pentesting a web application, if you come across any of the above-mentioned attributes, then it most probably uses GraphQL.
How to configure the GraphQL server?
We can run the GraphQL API server on localhost with the use of Express, a web application framework for Node.js.
- For this, after you have installed “npm” proceed to install two additional dependencies which can be done using the following command:
npm install express express-graphql graphql --save
- For more clarity of the concept, this is how we fetch “hello world” data from the GraphQL server using a query.
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
type Query {
hello: String
}
`);
// The root provides a resolver function for each API endpoint
var root = {
hello: () => {
return 'Hello world!';
},
};
var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at http://localhost:4000/graphql');
- Save the subsequent code as GraphQL_Server.js.
- Now, run this GraphQL server with:
node GraphQL_Server.js
- If you don’t encounter an error, that means we have successfully configured our GraphQL server and we are good to proceed.
- Navigate to the endpoint http://locahost:4000/graphql in a web browser where you will come across the GraphQL interface. You can now enter your queries here.
- Once the query “hello” is issued, it fetches the following data from the server:
Root types of GraphQL schema
GraphQL schema has three root types. Requests against GraphQL endpoint should start with any of these root types while communicating with the server:
- Query: This type allows reading or fetching data from the backend server.
- Mutation: This type is used to create, edit, or delete data.
- Subscriptions: This root type enables real-time communication, to automatically receive real-time updates about particular events.
GraphQL is said to be client-driven, as it allows clients to add new fields and types to the GraphQL API and provide each field with functions. Clients can ultimately decide the exact response they require for queries. Contrary to how REST API operates, GraphQL permits clients to retrieve essential data alone, instead of the complete data.
GraphQL vs. REST
Both REST and GraphQL help developers design the functioning of APIs, and the process by which applications will be able to access data from it. They send data over HTTP. However, there are quite a few differences between them which prove that GraphQL is superior.
A key differentiator is a method of fetching data from the backend server. While a typical REST API sends multiple requests to load data from multiple URLs, GraphQL has to send only a single request, to get the most accurate response, leaving out unwanted data behind. This is called declarative data fetching. Here’s an example to help you understand this better.
In REST API, multiple requests are sent at multiple endpoints to fetch the specific or particular data from the server. For instance, in order to fetch a user’s ID, his posts on a social media platform, and his followers on the same channel, we have to send multiple requests at the endpoint using the right path such as /user/<id>, /users/id/<posts>, and /users/id/<followers> respectively, only to get multiple responses regarding the same.
However, in the case of GraphQL, a single query, that includes all three requests, at a single endpoint will be enough to retrieve accurate responses to the corresponding requests. All we need to do is send a query through the interface, which gets interpreted against the entire schema, and returns the exact data that the client requested.
Smooth, declarative data fetching
In the instance of REST API mentioned above, we saw that 3 requests were made at 3 different endpoints to retrieve the corresponding response from the server. But in GraphQL, this process is relatively easier. A query that includes the exact data requirements like IDs, posts, and followers at a single endpoint would do the job.
Let’s have a look at the query that is sent to the server to fetch a user’s ID, posts, and followers:
The above image shows how a query that includes data requirements is sent to the backend server, for which it’s response is retrieved at the client-side.
The dissimilarities between REST and GraphQL is quite significant and can be understood while comparing their functioning.
However, these differences do not necessarily mean that REST is not as efficient or flexible, after all it has been the standard API for several years now. However, GraphQL is gaining popularity because it addresses and bridges the shortcomings of REST API.
In next week’s blog, we will explore the common GraphQL misconfigurations that enable hackers, and how you can test them.