توليد Swagger/OpenAPI لـ Rust: مكتبة Utoipa

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

توليد Swagger/OpenAPI لـ Rust: Utoipa — أداة حديثة للتوثيق التلقائي

\n\n

عند تطوير تطبيقات الويب بلغة Rust، فإن توثيق API ليس رفاهية بل ضرورة. توفر مكتبة Utoipa (اختصار لـ "Utopia") طريقة قوية وأنيقة لتوليد مواصفات OpenAPI مباشرة من الكود. تتكامل مع أطر العمل الشائعة مثل actix-web و axum و rocket و warp، وتسمح بوصف نقاط النهاية ومخططات البيانات والمعاملات باستخدام السمات والماكرو.

\n\n

الميزات الرئيسية لـ Utoipa

\n
    \n
  • توليد تلقائي لـ OpenAPI 3.0/3.1 — دون كتابة يدوية لـ YAML/JSON.
  • \n
  • دعم أطر عمل متعددة — actix-web, axum, rocket, warp.
  • \n
  • التكامل مع Swagger UI — مكون مدمج لعرض التوثيق بشكل مرئي.
  • \n
  • وصف عميق للمخططات — دعم الهياكل المتداخلة، التعدادات، الحقول الاختيارية.
  • \n
  • ماكرو للوصف السريع — #[utoipa::path], #[openapi].
  • \n
  • التحقق من صحة المواصفات — التأكد من صحة المستند المُنشأ.
  • \n
\n\n

التثبيت والإعداد

\n

أضف التبعيات في ملف Cargo.toml. على سبيل المثال، سنختار إطار العمل actix-web:

\n
[dependencies]\nutoipa = "4"\nutoipa-swagger-ui = { version = "4", features = ["actix-web"] }\nactix-web = "4"\nserde = { version = "1", features = ["derive"] }\n
\n\n

مثال أساسي: إنشاء API مع التوثيق

\n

لننظر إلى CRUD بسيط لكيان "مستخدم". نبدأ بتعريف نموذج البيانات:

\n
use serde::{Deserialize, Serialize};\nuse utoipa::ToSchema;\n\n#[derive(Serialize, Deserialize, ToSchema)]\npub struct User {\n    #[schema(example = "1")]\n    pub id: i32,\n    #[schema(example = "john_doe")]\n    pub username: String,\n    #[schema(example = "john@example.com")]\n    pub email: String,\n}\n
\n

الآن نصف نقطة نهاية الحصول على قائمة المستخدمين باستخدام الماكرو #[utoipa::path]:

\n
use actix_web::{get, web, HttpResponse, Responder};\nuse utoipa::OpenApi;\n\n#[utoipa::path(\n    get,\n    path = "/users",\n    responses(\n        (status = 200, description = "قائمة المستخدمين", body = Vec<User>)\n    )\n)]\n#[get("/users")]\nasync fn get_users() -> impl Responder {\n    let users = vec![\n        User { id: 1, username: "alice".into(), email: "alice@example.com".into() },\n        User { id: 2, username: "bob".into(), email: "bob@example.com".into() },\n    ];\n    HttpResponse::Ok().json(users)\n}\n
\n\n

بناء مستند OpenAPI و Swagger UI

\n

ننشئ هيكلًا لوصف API بالكامل:

\n
#[derive(OpenApi)]\n#[openapi(\n    paths(get_users),\n    components(schemas(User))\n)]\npub struct ApiDoc;\n\n// في الدالة main نقوم بإعداد Swagger UI\nuse utoipa_swagger_ui::SwaggerUi;\n\n#[actix_web::main]\nasync fn main() -> std::io::Result<()> {\n    use actix_web::App;\n\n    HttpServer::new(|| {\n        App::new()\n            .service(get_users)\n            .service(\n                SwaggerUi::new("/swagger-ui/{_:.*}")\n                    .url("/api-docs/openapi.json", ApiDoc::openapi())\n            )\n    })\n    .bind("127.0.0.1:8080")?\n    .run()\n    .await\n}\n
\n

بعد تشغيل التطبيق، سيكون التوثيق متاحًا على الرابط http://localhost:8080/swagger-ui/.

\n\n

ميزات متقدمة: المخططات المتداخلة والمعاملات

\n

يدعم Utoipa أنواع البيانات المعقدة. على سبيل المثال، نضيف حقلًا بهيكل متداخل:

\n
#[derive(Serialize, Deserialize, ToSchema)]\npub struct Address {\n    #[schema(example = "موسكو")]\n    pub city: String,\n    #[schema(example = "شارع لينين، مبنى 1")]\n    pub street: String,\n}\n\n                    

توصيات