عميل HTTP بلغة Rust: إجراء الطلبات بشكل صحيح
Rust هي لغة برمجة نظام حديثة تجمع بين أداء C++ وأمان الذاكرة. عند تطوير تطبيقات الويب أو الخدمات المصغرة أو أدوات سطر الأوامر، غالبًا ما تنشأ الحاجة للتفاعل مع واجهات برمجة التطبيقات الخارجية. في هذه المقالة، سنشرح كيفية إنشاء عميل HTTP بلغة Rust باستخدام الكريتات الشهيرة reqwest و ureq. ستتعلم كيفية إرسال طلبات GET و POST، ومعالجة الأخطاء، والعمل مع JSON.
لماذا Rust لطلبات HTTP؟
تقدم Rust مزايا فريدة للعمل مع الشبكة:
- أمان الذاكرة — يضمن المترجم عدم وجود تسرب للذاكرة أو سباقات البيانات.
- أداء عالٍ — سرعة مماثلة لـ C/C++.
- البرمجة غير المتزامنة — دعم مدمج لـ async/await للعمل الفعال مع الإدخال/الإخراج.
- نظام الكريتات البيئي — آلاف المكتبات الجاهزة، بما في ذلك عملاء HTTP.
للعمل مع HTTP في Rust، هناك طريقتان رئيسيتان: متزامنة (حظر) وغير متزامنة (غير حظر). سننظر في كلتيهما.
إعداد المشروع واختيار الكريت
لنقم بإنشاء مشروع Rust جديد:
cargo new rust-http-clientcd rust-http-clientافتح Cargo.toml وأضف التبعيات:
[dependencies]# للطلبات غير المتزامنةreqwest = { version = "0.12", features = ["json"] }tokio = { version = "1", features = ["full"] }
# للطلبات المتزامنة (بديل)ureq = "2.9"مقارنة الكريتات:
- reqwest — عميل HTTP الأكثر شيوعًا. يدعم البرمجة غير المتزامنة، JSON، الكوكيز، البروكسي.
- ureq — عميل متزامن خفيف الوزن. مثالي للنصوص البسيطة وأدوات CLI.
1. طلب GET باستخدام reqwest (غير متزامن)
لنبدأ بطلب GET غير متزامن. قم بإنشاء ملف src/main.rs:
use reqwest;use std::error::Error;
#[tokio::main]async fn main() -> Result<(), Box<dyn Error>> { // إرسال طلب GET let response = reqwest::get("https://api.github.com/repos/rust-lang/rust") .await? .text() .await?;
println!("الرد من GitHub API:"); println!("{}", &response[..500]); // طباعة أول 500 حرف
Ok(())}الشرح:
#[tokio::main]— ماكرو لتشغيل بيئة Tokio غير المتزامنة.reqwest::get()— يرسل طلب GET ويعيدResponse..await?— ينتظر اكتمال العملية ويعالج الأخطاء..text()— يستخرج نص الاستجابة كسلسلة نصية.
قم بتشغيل المشروع:
cargo runسترى رد JSON من GitHub API.
2. طلب POST مع JSON (reqwest)
الآن سنرسل طلب POST مع نص بتنسيق JSON:
use reqwest;use serde::{Deserialize, Serialize};use std::error::Error;
#[derive(Serialize, Deserialize, Debug)]struct Post { title: String, body: String, user_id: u32,}
#[derive(Deserialize, Debug)]struct CreatedPost { id: u32, title: String,}
#[tokio::main]async fn main() -> Result<(), Box<dyn Error>> { // إنشاء عميل مع إعدادات let client = reqwest::Client::new();
// البيانات المراد إرسالها let new_post = Post { title: "عميل HTTP بلغة Rust".to_string(), body: "دليل كامل للعمل مع HTTP في Rust".to_string(), user_id: 1, };
// إرسال طلب POST let response = client .post("https://jsonplaceholder.typicode.com/posts") .json(&new_post) .send() .await?;
//
```