Введение: Почему C++ для REST API?
C++ традиционно ассоциируется с системным программированием, играми и высоконагруженными приложениями. Однако современный C++ (стандарты C++17 и C++20) вместе с легковесными библиотеками позволяет создавать быстрые и эффективные веб-сервисы. Если вам нужно REST API, которое обрабатывает тысячи запросов в секунду с минимальной задержкой, C++ — отличный выбор.
В этой статье мы за 30 минут создадим полноценный REST API на C++ с использованием библиотеки Crow. Это мини-фреймворк, похожий на Python Flask, но написанный на C++. Мы настроим маршруты, научимся парсить JSON и отдавать ответы.
Шаг 1: Подготовка окружения и установка Crow
Для работы нам понадобится компилятор с поддержкой C++17 (GCC 7+, Clang 5+, MSVC 2019+) и менеджер зависимостей vcpkg или Conan. Самый простой способ — скачать Crow в виде заголовочного файла (header-only).
1.1 Установка через vcpkg (рекомендуется)
Если у вас установлен vcpkg, выполните команду:
vcpkg install crow
Затем при компиляции укажите путь к библиотекам:
g++ main.cpp -std=c++17 -I/path/to/vcpkg/installed/x64-linux/include -lpthread -o server
1.2 Установка вручную (header-only)
Скачайте последнюю версию Crow с GitHub. Вам нужен только файл crow_all.h (все включено). Поместите его в папку с проектом.
Шаг 2: Создание простого сервера с двумя эндпоинтами
Напишем минимальный сервер, который слушает порт 8080 и отвечает на GET и POST запросы. Создайте файл main.cpp.
2.1 Базовый код сервера
#include "crow_all.h"
int main() {
crow::SimpleApp app;
// GET-эндпоинт: корневая страница
CROW_ROUTE(app, "/")([](){
return "Hello, REST API on C++!";
});
// GET-эндпоинт: /api/status
CROW_ROUTE(app, "/api/status")([](){
crow::json::wvalue response;
response["status"] = "ok";
response["message"] = "Server is running";
return response;
});
app.port(8080).multithreaded().run();
}
Скомпилируйте и запустите:
g++ main.cpp -std=c++17 -lpthread -o api_server
./api_server
Теперь перейдите в браузере на http://localhost:8080/api/status — вы увидите JSON-ответ.
Шаг 3: Работа с JSON и обработка POST-запросов
Настоящее REST API подразумевает получение данных от клиента. Научимся принимать JSON в теле запроса.
3.1 POST-эндпоинт для создания пользователя
#include "crow_all.h"
#include <string>
#include <unordered_map>
int main() {
crow::SimpleApp app;
// Простое in-memory хранилище (для демонстрации)
std::unordered_map<int, std::string> users;
int next_id = 1;
// POST /api/users — создать пользователя
CROW_ROUTE(app, "/api/users").methods("POST"_method)([&](const crow::request& req){
auto body = crow::json::load(req.body);
if (!body || !body.has("name")) {
return crow::response(400, "Missing 'name' field");
}
std::string name = body["name"].s();
int id = next_id++;
users[id] = name;
crow::json::wvalue response;
response["id"] = id;
response["name"] = name;
return crow::response(201, response);
});
// GET /api/users/{id} — получить пользователя
CROW_ROUTE(app, "/api/users/<int>")([&](int id){
auto it = users.find(id);
if (it == users.end()) {
return crow::response(404, "User not found");
}
crow::json::wvalue response;
response["id"] = id;
response["name"] = it->second;
return crow::response(response);
});
app.port(8080).multithreaded().run();
}
3.2 Тестирование с помощью curl
Откройте новый терминал и выполните:
# Создать пользователя
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice"}'
# Получить пользователя
curl http://localhost:8080/api/users/1
Вы должны получить JSON с id и name.
Шаг 4: Добавляем CORS и обработку ошибок
Чтобы вашим API могли пользоваться фронтенд-приложения, нужно настроить CORS (Cross-Origin Resource Sharing). Crow поддерживает middleware.
4.1 Middleware для CORS
#include "crow_all.h"
struct CORSMiddleware {
struct context {};
void before_handle(crow::request& req, crow::response& res, context& /*ctx*/) {
res.add_header("Access-Control-Allow-Origin", "*");
res.add_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.add_header("Access-Control-Allow-Headers", "Content-Type, Authorization");
// Обработка preflight запросов (OPTIONS)
if (req.method == "OPTIONS"_method) {
res.code = 204;
res.end();
}
}
void after_handle(crow::request& req, crow::response& res, context& /*ctx*/) {
// ничего не делаем
}
};
int main() {
crow::App<CORSMiddleware> app;
// ... ваши маршруты ...
app.port(8080).multithreaded().run();
}
4.2 Обработка 404 и глобальных ошибок
// В конце main() перед app.run()
CROW_ROUTE(app, "/<string>")([](std::string path){
crow::json::wvalue error;
error["error"] = "Not Found";
error["path"] = path;
return crow::response(404, error);
});
Теперь любой запрос к несуществующему маршруту вернёт JSON-