مقدمة: لماذا C++ لواجهات REST API؟
يرتبط C++ تقليديًا ببرمجة الأنظمة والألعاب والتطبيقات عالية التحميل. ومع ذلك، فإن لغة C++ الحديثة (معايير C++17 و C++20) إلى جانب المكتبات خفيفة الوزن تسمح بإنشاء خدمات ويب سريعة وفعالة. إذا كنت بحاجة إلى REST API يعالج آلاف الطلبات في الثانية بأقل تأخير، فإن C++ هو خيار ممتاز.
في هذه المقالة، سنقوم خلال 30 دقيقة بإنشاء REST API كامل بلغة C++ باستخدام مكتبة Crow. هذا إطار عمل مصغر، يشبه Python Flask، ولكنه مكتوب بلغة C++. سنقوم بإعداد المسارات (Routes)، وتعلم كيفية تحليل 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: إنشاء خادم بسيط بنقطتي نهاية (Endpoints)
لنكتب خادمًا أدنى يستمع على المنفذ 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;
// تخزين بسيط في الذاكرة (للتوضيح)
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);
});
```