توليد Swagger/OpenAPI لـ Rust: Utoipa و Aide

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

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

ابدأ الدورة

توليد Swagger/OpenAPI لـ Rust: Utoipa و Aide



في تطوير الويب الحديث باستخدام Rust، لم يعد إنشاء API موثق رفاهية بل ضرورة. يتيح Swagger (OpenAPI) التوليد التلقائي للتوثيق التفاعلي، وSDK الخاصة بالعميل، ووحدات التحكم الاختبارية. في النظام البيئي لـ Rust، هناك أداتان رائدتان: Utoipa (القائمة على الماكرو) و Aide (التي تركز على تحديد الأنواع والتحكم اليدوي). دعنا نستعرضهما بالتفصيل.



Utoipa — ماكرو لـ OpenAPI 3.0



Utoipa هي مكتبة تستخدم سمات الماكرو (#[utoipa::path]) للتوليد التلقائي لمواصفات OpenAPI. تتكامل بشكل وثيق مع الأطر الشائعة: Actix-web، Axum، Rocket، Warp.



الميزات:

  • دعم كامل لـ OpenAPI 3.0 (المسارات، المكونات، مخططات الأمان).
  • استخراج تلقائي للأنواع من هياكل Rust (باستخدام #[derive(ToSchema)]).
  • توليد ملف JSON/YAML لواجهة Swagger UI.
  • دعم actix-web مباشرة (عبر utoipa-swagger-ui).
  • عتبة دخول منخفضة — فقط أضف الماكرو.


مثال مع Actix-web:

use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};use serde::{Deserialize, Serialize};use utoipa::{OpenApi, ToSchema};use utoipa_swagger_ui::SwaggerUi;

#[derive(Serialize, Deserialize, ToSchema)]struct User { id: u32, name: String,}

#[utoipa::path( get, path = "/users/{id}", responses( (status = 200, description = "تم العثور على المستخدم", body = User), (status = 404, description = "لم يتم العثور على المستخدم") ), params( ("id" = u32, Path, description = "معرف المستخدم") ))]#[get("/users/{id}")]async fn get_user(id: web::Path<u32>) -> impl Responder { HttpResponse::Ok().json(User { id: id.into_inner(), name: "أليس".into(), })}

#[derive(OpenApi)]#[openapi(paths(get_user), components(schemas(User)))]struct ApiDoc;

#[actix_web::main]async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .service(get_user) .service( SwaggerUi::new("/swagger-ui/{_:.*}") .url("/api-doc/openapi.json", ApiDoc::openapi()), ) }) .bind("127.0.0.1:8080")? .run() .await}


Aide — التحكم وتحديد الأنواع



Aide (سابقًا paperclip) تقدم نهجًا مختلفًا: تصف المواصفات بشكل صريح من خلال الهياكل والدوال، وليس من خلال الماكرو. يمنحك هذا تحكمًا أكبر، لكنه يتطلب حجمًا أكبر من الكود. تدعم المكتبة Axum و Actix-web.



الميزات:

  • تحديد أنواع نقي — جميع الأوصاف تُعطى من خلال enum و struct.
  • التحقق المدمج من المخططات أثناء التوليد.
  • دعم النماذج المتداخلة والتراكيب (allOf, oneOf).
  • المرونة: يمكنك تجاوز أي جانب من جوانب المواصفات.


مثال مع Axum:

use aide::{axum::ApiRouter, openapi::OpenApi};use axum::{routing::get, Json, Router};use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]struct Pet { id: u32, name: String,}

async fn list_pets() -> Json<Vec<Pet>> { Json(vec![Pet { id: 1, name: "ريكس".into(), }])}

async fn api_docs() -> Json<OpenApi> { let mut api = OpenApi::default(); api.info.title = "Pet Store API".into(); api.info.version = "1.0.0".into(); Json(api)}

#[tokio::main]async fn main() { let app = ApiRouter::new() .route("/pets", get(list_pets)) .route("/api-doc", get(api_docs));

axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap();}

توصيات