GraphQL на C++: cppgraphqlgen — мощный инструмент для современных API
GraphQL — это язык запросов для API, который позволяет клиентам получать только необходимые данные. Хотя чаще всего GraphQL ассоциируется с JavaScript (Apollo, Relay) или Python (Graphene, Strawberry), для высоконагруженных систем на C++ также существует отличное решение — библиотека cppgraphqlgen. Она предоставляет полный набор инструментов для создания серверной части GraphQL на чистом C++ с поддержкой современных стандартов C++17/20.
Что такое cppgraphqlgen?
cppgraphqlgen — это header-only библиотека (с опциональной компиляцией в .so/.dll), которая реализует спецификацию GraphQL (June 2018). Она генерирует типобезопасный код на основе схемы (SDL — Schema Definition Language) и позволяет создавать эффективные, многопоточные серверы GraphQL.
Ключевые особенности:
- Генерация кода из схемы — вы описываете типы, запросы и мутации в
.graphqlфайле, а утилитаgraphqlgenсоздаёт C++ классы. - Типобезопасность — все типы проверяются на этапе компиляции. Никаких runtime-ошибок с типами.
- Производительность — минимальные накладные расходы, поддержка асинхронных резолверов (через
std::future). - Поддержка подписок (Subscriptions) — через WebSocket или gRPC.
- Интеграция с любым HTTP-сервером — можно использовать с
crow,drogon,beast(Boost.Asio) или даже собственной реализацией.
Архитектура библиотеки
cppgraphqlgen состоит из двух частей:
- Генератор кода (
graphqlgen) — читает схему и создаёт заголовочные файлы с классами для каждого типа, интерфейсами для резолверов и вспомогательными функциями. - Runtime-библиотека — парсер запросов, валидатор, исполнитель и сериализатор ответов.
Установка
Библиотека распространяется через vcpkg или собирается из исходников:
git clone https://github.com/microsoft/cppgraphqlgen.git
cd cppgraphqlgen
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --target install
Для использования генератора потребуется node.js (он написан на TypeScript), но runtime — чистый C++.
Пример: создание простого GraphQL-сервера
Сначала создадим схему schema.graphql:
type Query {
hello: String
user(id: Int!): User
}
type User {
id: Int
name: String
email: String
}
Затем запускаем генератор:
graphqlgen --schema schema.graphql --output ./generated
После этого в папке generated появятся файлы: SchemaTypes.h, SchemaResolver.h и другие. Теперь напишем резолверы:
#include "generated/SchemaTypes.h"
#include "generated/SchemaResolver.h"
class QueryResolver : public graphql::schema::Query::Resolver {
public:
std::shared_ptr<graphql::schema::String> getHello() override {
return std::make_shared<graphql::schema::String>("Hello, GraphQL from C++!");
}
std::shared_ptr<graphql::schema::User> getUser(int id) override {
auto user = std::make_shared<graphql::schema::User>();
user->id = std::make_shared<graphql::schema::Int>(id);
user->name = std::make_shared<graphql::schema::String>("John Doe");
user->email = std::make_shared<graphql::schema::String>("john@example.com");
return user;
}
};
Теперь собираем сервер с использованием crow:
#include <crow.h>
#include "generated/Schema.h"
int main() {
crow::SimpleApp app;
auto queryResolver = std::make_shared<QueryResolver>();
auto schema = graphql::schema::makeSchema(queryResolver);
CROW_ROUTE(app, "/graphql")
.methods("POST"_method)
([](const crow::request& req) {
auto query = req.body;
auto result = schema->execute(query);
return crow::response(result);
});
app.port(8080).multithreaded().run();
}