GraphQL API с C++: пошаговое руководство по созданию сервера

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

GraphQL API с C++: пошаговый туториал

GraphQL — это язык запросов для API, разработанный Facebook. В отличие от REST, он позволяет клиенту запрашивать только те данные, которые ему нужны, что снижает объем передаваемой информации и ускоряет работу приложений. В этом туториале мы создадим простой GraphQL сервер на C++ с использованием библиотеки graphql-cpp. Вы узнаете, как определить схему, написать резолверы и обрабатывать запросы и мутации.

Что такое GraphQL и почему C++?

GraphQL предоставляет единую конечную точку для всех запросов. Основные концепции:

  • Схема (Schema) — описание доступных типов данных и операций (запросы, мутации, подписки).
  • Запросы (Queries) — операции чтения данных.
  • Мутации (Mutations) — операции записи/изменения данных.
  • Резолверы (Resolvers) — функции, возвращающие данные для каждого поля.

C++ — мощный язык для высоконагруженных систем. Использование GraphQL с C++ позволяет создавать эффективные и масштабируемые API. Библиотека graphql-cpp предоставляет удобный интерфейс для интеграции.

Установка и настройка проекта

Для работы нам понадобятся:

  • Компилятор C++17 (например, g++ или MSVC).
  • Библиотека graphql-cpp (установка через vcpkg или сборка из исходников).
  • HTTP-сервер (мы будем использовать cpp-httplib для простоты).

Установка через vcpkg

vcpkg install graphql-cpp
vcpkg install cpp-httplib

Структура проекта

Создайте файлы:

  • main.cpp — точка входа и HTTP-сервер.
  • schema.hpp — определение схемы GraphQL.
  • resolvers.hpp — реализация резолверов.
  • CMakeLists.txt — конфигурация сборки.

Определение схемы GraphQL

Создадим простую схему для управления списком пользователей. Тип User содержит поля id, name и email. Запросы: users (список всех пользователей) и user(id: ID!) (один пользователь). Мутация: addUser(name: String!, email: String!): User.

В файле schema.hpp:

#ifndef SCHEMA_HPP
#define SCHEMA_HPP

#include <graphqlcpp/GraphQLSchema.h>

using namespace graphqlcpp;

// Определяем тип User
auto userType = std::make_shared<ObjectType>(
    "User",
    {
        {"id", Type::NonNull(Type::ID)},
        {"name", Type::NonNull(Type::String)},
        {"email", Type::NonNull(Type::String)}
    }
);

// Определяем Query
auto queryType = std::make_shared<ObjectType>(
    "Query",
    {
        {"users", Type::List(Type::NonNull(userType))},
        {"user", Type::NonNull(userType), {{"id", Type::NonNull(Type::ID)}}}
    }
);

// Определяем Mutation
auto mutationType = std::make_shared<ObjectType>(
    "Mutation",
    {
        {"addUser", Type::NonNull(userType), {
            {"name", Type::NonNull(Type::String)},
            {"email", Type::NonNull(Type::String)}
        }}
    }
);

// Собираем схему
auto schema = std::make_shared<Schema>(queryType, mutationType);

#endif // SCHEMA_HPP

Реализация резолверов

Резолверы — это функции, которые возвращают данные для каждого поля. В нашем примере данные будут храниться в глобальном векторе. В файле 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", "Alice", "alice@example.com"},
    {"2", "Bob", "bob@example.com"}
};

// Резолвер для списка пользователей
ResolveResult resolveUsers(const ResolveArgs& args) {
    return ResolveResult::list(users);
}

// Резолвер для одного пользователя
ResolveResult resolveUser(const ResolveArgs& args) {
    auto id = args.at("id").asString();
    for (const auto& user : users) {
        if (user.id == id) {
            return ResolveResult::object(user);
        }
    }
    return ResolveResult::null();
}

// Резолвер для мутации addUser
ResolveResult resolveAddUser(const ResolveArgs& args) {
    auto name = args.at("name").asString();
    auto email = args.at("email").asString();
    std::string newId = std::to_string(users.size() + 1);
    users.push_back({newId, name, email});
    return ResolveResult::object(users.back());
}

// Привязываем резолверы к полям схемы
void bindResolvers() {
    schema->getQueryType()->setResolver("users", resolveUsers);
    schema->getQueryType()->setResolver("user", resolveUser);
    schema->getMutationType()->setResolver("addUser", resolveAddUser);
}

#endif // RESOLVERS_HPP

Создание HTTP-сервера и обработка запросов

Теперь объединим всё в main.cpp. Используем cpp-httplib для создания простого HTTP-сервера, который принимает POST-запросы на /graphql и возвращает JSON-ответ.

#include <iostream>
#include <httplib.h>
#include <nlohmann/json.hpp>
#include "schema.hpp"
#include "resolvers.hpp"

using json = nlohmann::json;

int main() {
    bindResolvers();
    httplib::Server svr;

    svr.Post("/graphql", [](const httplib::Request& req, httplib::Response& res) {
        auto body = json::parse(req.body);
        std::string query = body["query"];
        // Выполняем запрос
        auto result = schema->execute(query);
        res.set_content(result.dump(), "application/json");
    });

    std::cout << "Сервер запущен на http://                

Блоги

Рекомендаций по книгам