GraphQL API на C++: пошаговый туториал с практическими примерами

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

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

Начать курс

Введение: GraphQL и C++ — мощный дуэт для современного API

GraphQL становится стандартом де-факто для построения гибких и эффективных API. В то время как большинство туториалов фокусируются на JavaScript или Python, C++ остаётся незаменимым для высоконагруженных систем, игровых серверов и встраиваемых решений. В этом пошаговом руководстве мы создадим полноценный GraphQL API на C++ с нуля, используя библиотеку graphql-cpp и сервер cpp-httplib.

Вы узнаете, как настроить окружение, определить схему, реализовать резолверы и запустить сервер. Все примеры кода можно сразу применить в реальных проектах.

1. Подготовка окружения и установка зависимостей

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

  • Компилятор с поддержкой C++17 (GCC 8+, Clang 7+, MSVC 2019+)
  • CMake (версия 3.14+)
  • Библиотека graphql-cpp (реализация GraphQL)
  • Библиотека cpp-httplib (HTTP-сервер)
  • Менеджер пакетов vcpkg (опционально, но удобно)

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

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg install graphql-cpp cpp-httplib nlohmann-json

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

graphql-cpp-api/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   ├── schema.cpp
│   ├── schema.h
│   ├── resolvers.cpp
│   └── resolvers.h
└── vcpkg.json

CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(GraphQLCppApi)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(graphql-cpp CONFIG REQUIRED)
find_package(cpp-httplib CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)

add_executable(graphql_server
    src/main.cpp
    src/schema.cpp
    src/resolvers.cpp
)

target_link_libraries(graphql_server
    graphql-cpp::graphql-cpp
    cpp-httplib::cpp-httplib
    nlohmann_json::nlohmann_json
)

Теперь всё готово к написанию кода.

2. Определение GraphQL схемы и типов

Начнём с создания схемы для простого API управления книгами. У нас будут типы Book и Author, а также запросы и мутации.

schema.h

#ifndef SCHEMA_H
#define SCHEMA_H

#include <graphqlcpp/GraphQLSchema.h>

std::shared_ptr<graphql::GraphQLSchema> createSchema();

#endif

schema.cpp

#include "schema.h"
#include "resolvers.h"

std::shared_ptr<graphql::GraphQLSchema> createSchema() {
    using namespace graphql;

    // Тип Author
    auto authorType = object_type("Author", {
        field("id", int_type()),
        field("name", string_type()),
        field("books", list_type(int_type()))
    });

    // Тип Book
    auto bookType = object_type("Book", {
        field("id", int_type()),
        field("title", string_type()),
        field("authorId", int_type()),
        field("year", int_type()),
        field("genre", string_type())
    });

    // Query root
    auto queryType = object_type("Query", {
        field("books", list_type(bookType), {
            argument("genre", string_type(), true)  // необязательный аргумент
        }, resolveBooks),
        field("book", bookType, {
            argument("id", int_type(), false)       // обязательный аргумент
        }, resolveBookById),
        field("authors", list_type(authorType), resolveAuthors)
    });

    // Mutation root
    auto mutationType = object_type("Mutation", {
        field("addBook", bookType, {
            argument("title", string_type(), false),
            argument("authorId", int_type(), false),
            argument("year", int_type(), false),
            argument("genre", string_type(), false)
        }, resolveAddBook),
        field("deleteBook", bool_type(), {
            argument("id", int_type(), false)
        }, resolveDeleteBook)
    });

    return std::make_shared<GraphQLSchema>(queryType, mutationType);
}

Обратите внимание на необязательные аргументы — они помечены true в конструкторе argument. Это позволяет клиентам запрашивать книги без фильтра по жанру.

3. Реализация резолверов с реальными данными

Теперь напишем резолверы — функции, которые возвращают данные для каждого поля схемы. Для простоты используем статический вектор в памяти, но в реальном проекте здесь будет подключение к БД.

resolvers.h

#ifndef RESOLVERS_H
#define RESOLVERS_H

#include <graphqlcpp/ResolveInfo.h>
#include <nlohmann/json.hpp>

nlohmann::json resolveBooks(const graphql::ResolveInfo& info);
nlohmann::json resolveBookById(const graphql::ResolveInfo& info);
nlohmann::json resolveAuthors(const graphql::ResolveInfo& info);
nlohmann::json resolveAddBook(const graphql::ResolveInfo& info);
nlohmann::json resolveDeleteBook(const graphql::ResolveInfo& info);

#endif

resolvers.cpp

#include "resolvers.h"
#include <vector>
#include <algorithm>
#include <stdexcept>

namespace {
    struct Book {
        int id;
        std::string title;
        int authorId;
        int year;
        std::string genre;
    };

    struct Author {
        int id;
        std::string name;
    };

    // Начальные данные
    std::vector<Book> books = {
        {1, "Война и мир", 1, 1869, "Роман"},
        {2, "Преступление и наказание", 2, 1866, "Роман"},
        {3, "Мастер и Маргарита", 3, 1967, "Фантастика"},
        {4, "Евгений Онегин", 4, 1833, "Поэзия"}
    };

    std::vector<Author> authors = {
        {1, "Лев Толстой"},
        {2, "Фёдор Достоевский"},
        {3, "Михаил Булгаков"},
        {4, "Александр Пушкин"}
    };

    int nextBookId = 5;
} // анонимное пространство имён

nlohmann::json resolveBooks(const graphql::ResolveInfo& info)                

Блоги

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