GraphQL API с C++: пошаговый туториал для начинающих

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

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

Начать курс

GraphQL API с C++: пошаговый туториал для начинающих

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

Почему C++? Этот язык обеспечивает высокую производительность, что критично для API с высокой нагрузкой. GraphQL на C++ часто используется в системах реального времени, игровых движках и высоконагруженных веб-сервисах. Начнём!

Установка и настройка окружения

Для работы нам понадобится компилятор с поддержкой C++17 (например, GCC 8+ или Clang 10+), CMake и библиотека graphql-cpp. Установим всё необходимое.

Шаг 1: Установка зависимостей

В Ubuntu/Debian выполните:

sudo apt update
sudo apt install build-essential cmake libboost-all-dev libssl-dev

Для macOS используйте Homebrew:

brew install cmake boost openssl

Шаг 2: Клонирование библиотеки graphql-cpp

Библиотека graphql-cpp — это легковесная реализация GraphQL на C++. Клонируем репозиторий:

git clone https://github.com/your-repo/graphql-cpp.git
cd graphql-cpp
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j4
sudo make install

После установки создадим новый проект. Структура папок:

my_graphql_api/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   └── schema.cpp
└── include/
    └── schema.h

Шаг 3: Настройка CMakeLists.txt

Создайте файл CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(GraphQLExample)

set(CMAKE_CXX_STANDARD 17)

find_package(graphql-cpp REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)

add_executable(graphql_example src/main.cpp src/schema.cpp)
target_include_directories(graphql_example PRIVATE include)
target_link_libraries(graphql_example graphql-cpp::graphql-cpp Boost::system)

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

Схема — это ядро GraphQL API. Она описывает типы данных, запросы (queries) и мутации (mutations). В нашем примере создадим API для управления списком книг.

Создание типа Book

В файле include/schema.h объявим структуру данных и функцию для создания схемы:

#ifndef SCHEMA_H
#define SCHEMA_H

#include <graphql-cpp/graphql.hpp>
#include <string>
#include <vector>

struct Book {
    int id;
    std::string title;
    std::string author;
    int year;
};

graphql::Schema createBookSchema();

#endif // SCHEMA_H

Реализация схемы

В файле src/schema.cpp определим типы и корневой запрос:

#include "schema.h"
#include <graphql-cpp/graphql.hpp>
#include <vector>
#include <memory>

using namespace graphql;

// Временное хранилище книг
std::vector<Book> books = {
    {1, "C++ Primer", "Stanley B. Lippman", 2012},
    {2, "Effective Modern C++", "Scott Meyers", 2014}
};

Schema createBookSchema() {
    // 1. Определяем тип Book
    ObjectType bookType("Book");
    bookType.addField("id", Type::NonNull(Type::Int()));
    bookType.addField("title", Type::NonNull(Type::String()));
    bookType.addField("author", Type::NonNull(Type::String()));
    bookType.addField("year", Type::Int());

    // 2. Определяем корневой запрос
    ObjectType queryType("Query");
    queryType.addField("books", Type::List(Type::NonNull(bookType)), 
        [](const auto& args) -> json {
            json result = json::array();
            for (const auto& book : books) {
                result.push_back({
                    {"id", book.id},
                    {"title", book.title},
                    {"author", book.author},
                    {"year", book.year}
                });
            }
            return result;
        }
    );

    queryType.addField("book", bookType, 
        [](const auto& args) -> json {
            int id = args.at("id").get<int>();
            for (const auto& book : books) {
                if (book.id == id) {
                    return {
                        {"id", book.id},
                        {"title", book.title},
                        {"author", book.author},
                        {"year", book.year}
                    };
                }
            }
            return nullptr; // null, если книга не найдена
        },
        // Аргументы поля
        {{"id", Type::NonNull(Type::Int())}}
    );

    // 3. Собираем схему
    Schema schema;
    schema.addType(bookType);
    schema.setQueryType(queryType);
    return schema;
}

Написание резолверов и запуск сервера

Резолверы — это функции, которые возвращают данные для каждого поля. В нашем примере они уже встроены в объявление полей. Теперь создадим HTTP-сервер, который будет принимать GraphQL-запросы.

Создание HTTP-сервера с Boost.Beast

В файле src/main.cpp напишем простой сервер на Boost.Beast:

#include "schema.h"
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <string>

using namespace boost::beast;
using namespace boost::asio;
using tcp = boost::asio::ip::tcp;

void handleRequest(http::request<http::string_body>& req, http::response<http::string_body>& res) {
    if (req.method() != http::verb::post) {
        res.result(http::status::method_not_allowed);
        res.body() = "Only POST requests allowed";
        return;
    }

    // Парсим GraphQL-запрос
    auto schema = createBookSchema();
    auto body = req.body();
    auto requestJson = nlohmann::json::parse(body);
    auto query = requestJson["query"].get<std::string>();

    // Выполняем запрос
    auto result = schema.execute(query);                

Блоги

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