GraphQL API with C++: Step-by-Step Tutorial
GraphQL is a query language for APIs developed by Facebook. Unlike REST, it allows the client to request only the data it needs, which reduces the amount of transmitted information and speeds up applications. In this tutorial, we will create a simple GraphQL server in C++ using the graphql-cpp library. You will learn how to define a schema, write resolvers, and handle queries and mutations.
What is GraphQL and Why C++?
GraphQL provides a single endpoint for all queries. The main concepts are:
- Schema — a description of available data types and operations (queries, mutations, subscriptions).
- Queries — read data operations.
- Mutations — write/modify data operations.
- Resolvers — functions that return data for each field.
C++ is a powerful language for high-load systems. Using GraphQL with C++ allows you to create efficient and scalable APIs. The graphql-cpp library provides a convenient interface for integration.
Project Setup and Configuration
For this we will need:
- C++17 compiler (e.g., g++ or MSVC).
graphql-cpplibrary (install via vcpkg or build from source).- HTTP server (we will use
cpp-httplibfor simplicity).
Installation via vcpkg
vcpkg install graphql-cppvcpkg install cpp-httplibProject Structure
Create the following files:
main.cpp— entry point and HTTP server.schema.hpp— GraphQL schema definition.resolvers.hpp— resolver implementation.CMakeLists.txt— build configuration.
Defining the GraphQL Schema
Let's create a simple schema for managing a list of users. The User type contains fields id, name, and email. Queries: users (list of all users) and user(id: ID!) (single user). Mutation: addUser(name: String!, email: String!): User.
In the file schema.hpp:
#ifndef SCHEMA_HPP#define SCHEMA_HPP
#include <graphqlcpp/GraphQLSchema.h>
using namespace graphqlcpp;
// Define the User typeauto userType = std::make_shared<ObjectType>( "User", { {"id", Type::NonNull(Type::ID)}, {"name", Type::NonNull(Type::String)}, {"email", Type::NonNull(Type::String)} });
// Define Queryauto queryType = std::make_shared<ObjectType>( "Query", { {"users", Type::List(Type::NonNull(userType))}, {"user", Type::NonNull(userType), {{"id", Type::NonNull(Type::ID)}}} });
// Define Mutationauto mutationType = std::make_shared<ObjectType>( "Mutation", { {"addUser", Type::NonNull(userType), { {"name", Type::NonNull(Type::String)}, {"email", Type::NonNull(Type::String)} }} });
// Build the schemaauto schema = std::make_shared<Schema>(queryType, mutationType);
#endif // SCHEMA_HPPImplementing Resolvers
Resolvers are functions that return data for each field. In our example, data will be stored in a global vector. In the file resolvers.hpp:
#ifndef RESOLVERS_HPP#define RESOLVERS_HPP
#include <vector>#include <string>#include <graphqlcpp/Resolvers.h>
using namespace graphqlcpp;
struct User { std::string id; std::string name; std::string email;};
std::vector<User> users = { {"1",