كيفية كتابة REST API بلغة Rust في 30 دقيقة: للمبتدئين

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

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

ابدأ الدورة

مقدمة: لماذا Rust لـ REST API؟

Rust هي لغة برمجة أنظمة حديثة تجمع بين أداء C++ وأمان الذاكرة. في السنوات الأخيرة، أصبحت خيارًا شائعًا لإنشاء خدمات ويب عالية التحميل. إذا كنت معتادًا بالفعل على Python وترغب في تجربة شيء جديد، فإن Rust ستكون خطوة رائعة إلى الأمام.

في هذه المقالة، سنقوم بإنشاء REST API كامل لإدارة قائمة المهام (Todo List) بلغة Rust باستخدام إطار العمل Actix-web. العملية بأكملها ستستغرق 30 دقيقة كحد أقصى إذا اتبعت التعليمات.



1. إعداد البيئة

تثبيت Rust

إذا لم يكن Rust مثبتًا لديك بعد، قم بتنفيذ الأمر التالي في الطرفية (لنظامي Linux/macOS):

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

لنظام Windows، قم بتنزيل المثبت من الموقع الرسمي.

بعد التثبيت، تحقق من الإصدار:

rustc --version


إنشاء المشروع

لنقم بإنشاء مشروع جديد باستخدام Cargo - مدير حزم Rust:

cargo new rust_todo_apicd rust_todo_api


إضافة التبعيات

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

[dependencies]actix-web = "4"actix-rt = "2"serde = { version = "1", features = ["derive"] }serde_json = "1"tokio = { version = "1", features = ["full"] }

احفظ الملف. سيقوم Cargo تلقائيًا بتحميل جميع المكتبات عند أول بناء.



2. إنشاء نموذج البيانات والتخزين

قبل كتابة نقاط النهاية، دعنا نحدد هيكل البيانات. سنستخدم متجهًا بسيطًا في الذاكرة (للغرض التوضيحي).



نموذج المهمة

أنشئ ملف src/models.rs:

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]pub struct Task { pub id: u32, pub title: String, pub completed: bool,}


التخزين العام

في src/main.rs سنضيف حالة عامة. لضمان سلامة الخيوط، نستخدم Mutex:

use std::sync::Mutex;use actix_web::{web, App, HttpServer, HttpResponse, HttpRequest, Responder};use models::Task;

mod models;

struct AppState { tasks: Mutex<Vec<Task>>, next_id: Mutex<u32>,}


3. تنفيذ نقاط نهاية CRUD

الآن سنكتب المعالجات الأساسية. جميعها ستستقبل حالة التطبيق عبر web::Data.



GET /tasks — الحصول على جميع المهام

async fn get_tasks(data: web::Data<AppState>) -> impl Responder {    let tasks = data.tasks.lock().unwrap();    HttpResponse::Ok().json(tasks.clone())}


POST /tasks — إنشاء مهمة جديدة

async fn create_task(data: web::Data<AppState>, body: web::Json<Task>) -> impl Responder {    let mut tasks = data.tasks.lock().unwrap();    let mut next_id = data.next_id.lock().unwrap();    let new_task = Task {        id: *next_id,        title: body.title.clone(),        completed: false,    };    tasks.push(new_task.clone());    *next_id += 1;    HttpResponse::Created().json(new_task)}


GET /tasks/{id} — الحصول على مهمة حسب المعرف

async fn get_task(data: web::Data<AppState>, path: web::Path<u32>) -> impl Responder {    let id = path.into_inner();    let tasks = data.tasks.lock().unwrap();    match tasks.iter().find(|t| t.id == id) {        Some(task) => HttpResponse::Ok().json(task),        None => HttpResponse::NotFound().json("Task not found"),    }}


DELETE /tasks/{id} — حذف مهمة

async fn delete_task(data: web::Data<AppState>, path: web::Path<u32>) -> impl Responder {    let id = path.into_inner();    l                

المدونات

توصيات الكتب