Swagger/OpenAPI генерация для C++: обзор инструментов и библиотек
Современная разработка серверных приложений на C++ редко обходится без REST API. Спецификация OpenAPI (ранее известная как Swagger) стала промышленным стандартом для описания интерфейсов взаимодействия между клиентом и сервером. Однако ручное написание кода для обработки запросов, валидации данных и генерации ответов — трудоёмкий и подверженный ошибкам процесс. К счастью, экосистема C++ предлагает несколько зрелых решений для автоматической генерации кода по OpenAPI-спецификации. В этой статье мы разберём основные инструменты, их сильные стороны и приведём практические примеры.
1. OpenAPI Generator (openapi-generator.tech)
Самый популярный универсальный генератор кода для десятков языков, включая C++. Поддерживает OpenAPI 3.0 и 3.1. Позволяет сгенерировать как серверный код (C++ REST SDK / cpprestsdk, Pistache, Restbed), так и клиентский код.
Установка
npm install @openapitools/openapi-generator-cli -g
# или через Docker:
docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
-i /local/petstore.yaml \
-g cpp-restsdk \
-o /local/out/cpp-client
Пример генерации клиента на cpprestsdk
Допустим, у вас есть файл petstore.yaml с описанием API для зоомагазина. После генерации вы получите готовые классы:
#include "ApiClient.h"
#include "PetApi.h"
int main() {
auto client = std::make_shared<ApiClient>();
PetApi api(client);
api.getPetById(1).then([](std::shared_ptr<Pet> pet) {
std::cout << "Pet name: " << pet->getName() << std::endl;
}).wait();
return 0;
}
Плюсы: огромное сообщество, поддержка множества фреймворков, активная разработка.
Минусы: сгенерированный код может быть избыточным, требует ручной донастройки под конкретный фреймворк.
2. oat++ (oatpp.io)
Современный фреймворк для C++ с собственной поддержкой OpenAPI 3.0. В отличие от OpenAPI Generator, oat++ не генерирует код из спецификации, а позволяет аннотировать уже написанные эндпоинты и автоматически экспортировать OpenAPI-спецификацию.
Пример аннотации эндпоинта
ENDPOINT("GET", "/pets/{petId}", getPetById) {
auto dto = PetDto::createShared();
dto->id = request->getPathVariable("petId");
dto->name = "Rex";
dto->status = "available";
return createDtoResponse(Status::CODE_200, dto);
}
// Описание DTO
DTO(PetDto,
FIELD(Int32, id, "id"),
FIELD(String, name, "name"),
FIELD(String, status, "status")
);
После этого oat++ автоматически сгенерирует openapi.json в рантайме. Для статической генерации используется утилита oatpp-swagger.
Плюсы: нативный подход, единый фреймворк, отличная документация, встроенная поддержка Swagger UI.
Минусы: требует использования oat++ целиком, не подходит для уже существующих проектов на других фреймворках.
3. Drogon (drogon.org)
Высокопроизводительный асинхронный веб-фреймворк для C++17/20. Включает модуль drogon_ctl для генерации скелета проекта и плагин drogon::OpenApiPlugin для автоматической генерации документации OpenAPI 3.0.
Пример использования OpenApiPlugin
#include <drogon/drogon.h>
using namespace drogon;
int main() {
app().registerController(std::make_shared<PetController>());
app().addPlugin("drogon::OpenApiPlugin", {
{"title", "Pet Store API"},
{"version", "1.0.0"}
});
app().run();
}
Контроллер с автодокументированием:
class PetController : public HttpController<PetController> {
public:
METHOD_LIST_BEGIN
ADD_METHOD_TO(PetController::getPetById, "/pets/{petId}", Get);
METHOD_LIST_END
void getPetById(const HttpRequestPtr& req,
std::function<void(const HttpResponsePtr&)>&& callback,
int petId) const {
Json::Value pet;
pet["id"] = petId;
pet["name"] = "Rex";
pet["status"] = "available";
auto resp