Работа с API на C++: REST, GraphQL, gRPC
Когда речь заходит о создании или потреблении API, многие разработчики по привычке тянутся к Python, Node.js или Go. Но как быть, если вам нужна максимальная производительность, низкоуровневый контроль над памятью или вы работаете в legacy-системе, где C++ — король? Ответ прост: C++ не просто жив — он процветает в мире API. Давайте разберем три ключевых подхода, которые должен знать каждый C++-разработчик: классический REST, современный GraphQL и высокопроизводительный gRPC.
Эта статья — не сухой справочник, а практическое руководство, написанное для тех, кто хочет писать реальный код. Мы рассмотрим, как эти технологии применяются на C++, приведем примеры с популярными библиотеками и поможем выбрать правильный инструмент для вашей задачи.
1. REST API на C++: классика в современном исполнении
REST (Representational State Transfer) остается самым распространенным стилем API. Его любят за простоту, человекочитаемость JSON и универсальность. На C++ у нас есть несколько мощных инструментов для работы с REST, и один из самых популярных — cpprestsdk (он же Casablanca) от Microsoft.
Пишем REST-клиент на C++
Представьте, что нам нужно получить данные о погоде от публичного API. Вот как это выглядит с cpprestsdk:
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <iostream>
using namespace web;
using namespace web::http;
using namespace web::http::client;
int main() {
// Создаем HTTP-клиент
http_client client(U("https://api.openweathermap.org/data/2.5"));
// Формируем GET-запрос с параметрами
uri_builder builder(U("/weather"));
builder.append_query(U("q"), U("Moscow"));
builder.append_query(U("appid"), U("YOUR_API_KEY"));
builder.append_query(U("units"), U("metric"));
// Отправляем запрос и получаем ответ
client.request(methods::GET, builder.to_string())
.then([](http_response response) {
if (response.status_code() == status_codes::OK) {
return response.extract_json();
}
throw std::runtime_error("Failed to fetch data");
})
.then([](json::value jsonData) {
std::cout << "Temperature: "
<< jsonData[U("main")][U("temp")].as_double()
<< "°C" << std::endl;
})
.wait();
return 0;
}
Ключевые моменты:
- Асинхронность: cpprestsdk использует PPL (Parallel Patterns Library) и futures, что идеально для C++.
- Работа с JSON: встроенный парсер json::value позволяет легко манипулировать данными.
- Кроссплатформенность: библиотека работает на Windows, Linux и macOS.
Когда выбирать REST?
REST на C++ идеален для:
- Простых CRUD-операций
- Интеграции с веб-сервисами (соцсети, платежные системы)
- Прототипирования и микросервисов с невысокой нагрузкой
2. GraphQL: гибкость запросов на C++
GraphQL решает главную проблему REST — overfetching (получение лишних данных) и underfetching (необходимость нескольких запросов для получения полной информации). На C++ для работы с GraphQL чаще всего используют библиотеку cppgraphql или пишут собственный клиент на основе libcurl.
Пример GraphQL-запроса на C++
Допустим, нам нужно получить профиль пользователя и его последние посты — в REST это потребовало бы два запроса, а в GraphQL — один:
#include <iostream>
#include <curl/curl.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
int main() {
CURL *curl = curl_easy_init();
std::string response;
if (curl) {
// GraphQL-запрос
std::string query = R"({
"query": "{
user(id: 42) {
name
email
posts(limit: 5) {
title
createdAt
}
}
}"
})";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/graphql");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl);
if (res == CURLE_OK) {
auto jsonResponse = json::parse(response);
std::cout << "User: " << jsonResponse["data"]["user"]["name"] << std::endl;
std::cout << "Posts count: " << jsonResponse["data"]["user"]["posts"].size() << std::endl;
}
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
}
return 0;
}
Почему это круто?
- Точность запросов: вы получаете ровно то, что нужно, без лишнего трафика.
- Снижение нагрузки: один запрос вместо нескольких.
- Типизация: GraphQL-схема строго типизирована, что упрощает обработку на C++.
Минусы GraphQL на C++
Главный недостаток — отсутствие mature-решений для серверной части. Если вы пишете GraphQL-клиент на C++, libcurl будет лучшим выбором. Для сервера придется использовать интеграцию с Node.js или Python.
3. gRPC: когда скорость критична
gRPC — это флагманский протокол Google для микросервисной архитектуры. Он использует Protocol Buffers (protobuf) для сериализации и HTTP/2 для транспорта. На C++ gRPC работает просто великолепно: минимальные накладные расходы, бинарный протокол и полная поддержка стриминга.
Настройка gRPC на C++
Сначала определим сервис в .proto-файле:
syntax = "proto3";
package weather;
service WeatherService {
rpc GetForecast (ForecastRequest) returns (ForecastResponse);
}
message ForecastRequest {
string city = 1;
int32 days = 2;
}
message ForecastResponse {
repeated DayForecast forecasts = 1;
}
message DayForecast {
string date = 1;
double temperature_max = 2;
double temperature_min = 3;
}
Теперь напишем сервер на C++:
#include <grpcpp/grpcpp.h>
#include "weather.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::Server