GraphQL API باستخدام Rust: دليل عملي خطوة بخطوة

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

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

ابدأ الدورة

مقدمة: لماذا Rust و GraphQL زوج مثالي

\n

تتطلب تطوير الويب الحديث أداءً عاليًا وكتابة صارمة للأنواع. Rust، المعروفة بأمان الذاكرة وسرعتها، أصبحت خيارًا ممتازًا لبناء الخوادم الخلفية. من ناحية أخرى، توفر GraphQL طريقة مرنة وفعالة للعمل مع البيانات. في هذا الدليل التعليمي، سنقوم بإنشاء GraphQL API كامل باستخدام Rust، باستخدام المكتبة async-graphql وإطار العمل actix-web. ستتعلم كيفية تعريف المخططات، كتابة المحللين (Resolvers)، ومعالجة الاستعلامات.

\n

في نهاية المقال، سيكون لديك خادم عامل جاهز للتكامل مع المشاريع الحقيقية. جميع أمثلة الكود تم اختبارها وجاهزة للتشغيل.

\n\n

إعداد المشروع وتثبيت التبعيات

\n

للبدء، سنقوم بإنشاء مشروع Rust جديد. تأكد من تثبيت Rust (يُوصى بالإصدار 1.75+).

\n
cargo new graphql-rust-api\ncd graphql-rust-api
\n

افتح ملف Cargo.toml وأضف التبعيات التالية:

\n
[dependencies]\nactix-web = "4"\nactix-rt = "2"\nasync-graphql = "7"\nasync-graphql-actix-web = "7"\nserde = { version = "1", features = ["derive"] }\ntokio = { version = "1", features = ["macros"] }
\n

قم بتشغيل cargo build لتحميل وتجميع جميع التبعيات. قد يستغرق ذلك بضع دقائق عند التشغيل الأول.

\n\n

هيكل المشروع

\n

أنشئ هيكل المجلدات والملفات التالي:

\n
src/\n├── main.rs\n├── schema.rs\n├── models.rs\n└── resolvers.rs
\n

سنقوم بملء كل ملف تدريجيًا.

\n\n

تعريف النماذج ومخطط GraphQL

\n

لنبدأ بإنشاء نموذج بيانات بسيط. في ملف models.rs، سنصف هيكل User:

\n
use serde::{Deserialize, Serialize};\n\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub struct User {\n    pub id: u32,\n    pub name: String,\n    pub email: String,\n}
\n

الآن ننتقل إلى schema.rs. هنا سنقوم بتعريف كائنات GraphQL والاستعلامات:

\n
use async_graphql::{Context, Object, SimpleObject};\nuse crate::models::User;\nuse crate::resolvers::get_all_users;\n\n#[derive(SimpleObject)]\npub struct UserObject {\n    pub id: u32,\n    pub name: String,\n    pub email: String,\n}\n\npub struct QueryRoot;\n\n#[Object]\nimpl QueryRoot {\n    async fn users(&self, ctx: &Context<'_>) -> Vec<UserObject> {\n        let users = get_all_users(ctx).await;\n        users.into_iter().map(|u| UserObject {\n            id: u.id,\n            name: u.name,\n            email: u.email,\n        }).collect()\n    }\n}
\n

لاحظ استخدام #[derive(SimpleObject)] - وهو ماكرو من async-graphql يقوم تلقائيًا بإنشاء نوع GraphQL.

\n\n

المحللون (Resolvers): منطق الأعمال

\n

في ملف resolvers.rs، سنقوم بتنفيذ دالة جلب البيانات. للتبسيط، سنستخدم قائمة ثابتة:

\n
use async_graphql::Context;\nuse crate::models::User;\n\npub async fn get_all_users(_ctx: &Context<'_>) -> Vec<User> {\n    vec![\n        User { id: 1, name: "Alice".into(), email: "alice@example.com".into() },\n        User { id: 2, name: "Bob".into(), email: "bob@example.com".into() },\n        User { id: 3, name: "Charlie".into(), email: "charlie@example.com".into() },\n    ]\n}
\n

في مشروع حقيقي، قد يكون هنا استدعاء لقاعدة بيانات أو API خارجي.

\n\n

بناء الخادم باستخدام Actix-web

\n

الآن الجزء الأهم - تجميع كل شيء معًا في ملف main.rs:

\n
use actix_web::{web, App, HttpServer, HttpResponse};\nuse async_graphql::{Schema, EmptyMutation, EmptySubscription};\nuse async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};\nuse crate::schema::QueryRoot;\n\nmod models;\nmod schema;\nmod resolvers;\n\ntype AppSchema = Schema<QueryRoot, EmptyMutation, EmptySubscription>;\n\nasync fn graphql_handler(\n    schema                

المدونات

توصيات الكتب