۳۰ آذر ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

۵ چارچوب وب محبوب Rust – کدام یک برای شما مناسب است؟

از سادگی Poem تا سرعت کامل Actix، چارچوب وب Rust برای اکثر کاربران و نیازها وجود دارد.

از سادگی Poem تا سرعت کامل Actix، چارچوب وب Rust برای اکثر کاربران و نیازها وجود دارد.

در حدود یک دهه گذشته، مجموعه‌ای از چارچوب‌های وب Rust ظاهر شده‌اند که هر کدام با کاربران و نیازهای ویژگی‌های کمی متفاوت ساخته شده‌اند. همه آنها از ایمنی نوع Rust، ایمنی حافظه، سرعت و صحت بهره مند هستند.

این مقاله نگاهی گذرا به پنج مورد از محبوب‌ترین چارچوب‌های وب Rust دارد: Actix Web، Rocket، Warp، Axum و Poem. همه آنها عناصر مشترکی را برای خدمات وب ارائه می کنند: مسیریابی، رسیدگی به درخواست، انواع پاسخ های متعدد و میان افزار. توجه داشته باشید که این چارچوب‌ها قالب‌بندی را ارائه نمی‌کنند، که معمولاً توسط جعبه‌های جداگانه مدیریت می‌شود.

Actix Web

Actix Web به راحتی محبوب ترین چارچوب وب برای Rust است. تقریباً همه نیازهای اصلی را برآورده می کند: عملکرد بالایی دارد، از طیف گسترده ای از ویژگی های سرور پشتیبانی می کند و برای جمع آوری یک سایت اصلی به مراسم کمی نیاز دارد.

نام “Actix Web” در اصل به وابستگی فریم‌ورک به چارچوب بازیگر actix اشاره داشت، اما این فریم‌ورک مدتی پیش عمدتاً این وابستگی را از بین برد. همه ویژگی های Actix Web در شاخه پایدار Rust در دسترس هستند.

در اینجا یک برنامه اولیه “Hello world” در Actix Web آمده است:


use actix_web::{get, App, HttpResponse, HttpServer, Responder};

#[get("/")]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body("Hello world!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(hello))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

ویژگی get() در تابع hello() نشان می‌دهد که در چه مسیری قرار است سرویس دهد، اما تا زمانی که به اضافه نشود فعال نیست. شیء App با روش .service(). Actix Web همچنین از ساخت مسیر پیشرفته‌تر پشتیبانی می‌کند—به عنوان مثال، می‌توانید متغیرهای موقعیتی را از URL ضبط کنید و از آن‌ها برای هدایت درخواست‌ها به توابعی که از get() استفاده نمی‌کنند استفاده کنید.

عملکرد برای Actix Web یک امتیاز بزرگ است. همه درخواست‌ها و پاسخ‌ها به‌عنوان انواع مجزا بررسی می‌شوند. سرور از یک Thread Pool برای رسیدگی به درخواست‌ها استفاده می‌کند و هیچ چیزی بین رشته‌ها به اشتراک گذاشته نمی‌شود تا عملکرد را به حداکثر برساند. در صورت نیاز می‌توانید با استفاده از Arc<> وضعیت را به‌صورت دستی به اشتراک بگذارید، اما نگه‌دارنده‌های Actix Web از انجام هر کاری که رشته های کارگر را مسدود می کند و در نتیجه عملکرد را خراب می کند، اصرار نکنید. برای کارهای طولانی مدت بدون CPU، از قراردادهای آتی یا غیر همگام استفاده کنید.

Actix Web همچنین کنترل‌کننده‌های مبتنی بر نوع کدهای خطا را ارائه می‌کند و از یک سیستم میان‌افزار داخلی (که می‌توانید از آن نیز استفاده کنید) برای پیاده‌سازی گزارش استفاده می‌کند. این چارچوب همچنین شامل یک سیستم مدیریت جلسه کاربر همه منظوره با کوکی‌ها به عنوان نوع ذخیره‌سازی پیش‌فرض است، اگرچه در صورت تمایل می‌توانید موارد دیگری را اضافه کنید. فایل‌ها و دایرکتوری‌های ایستا را نیز می‌توان با کنترل‌کننده‌های اختصاصی خود ارائه کرد.

بسیاری از توابع متداول سرویس وب همراه با Actix Web همراه با برخی از آنها که کمتر رایج هستند، ارائه می‌شوند. اینها شامل مدیریت بدنه‌های کدگذاری شده با URL برای فرم‌ها، ارتقای خودکار به HTTPS/2، فشرده‌سازی Brotli، gzip، deflate و zstd-فشرده‌شده است. و مدیریت کدگذاری تکه تکه شده. برای WebSockets، Actix Web به جعبه actix-web-actors نیاز دارد که یکی از وابستگی های اصلی آن است. به همین ترتیب، برای جریان های چند قسمتی، به جعبه actix-multipart نیاز دارید. (برای تبدیل به JSON و از آن، Actix Web از serde و serde_json استفاده می‌کند، که معمولاً برای کاربران Rust باید آشنا باشد.)

امیدی جدید برای امنیت نرم افزار

Actix Web در سال ۲۰۲۰ زمانی که نگهدارنده اصلی آن پروژه را ترک کرد، توجهات را به خود جلب کرد، ظاهراً به دلیل انتقاد در مورد استفاده از کد ناامن. با این حال، سایر نگهبانان اصلی به توسعه این چارچوب ادامه دادند و در سال‌های پس از آن به رشد خود ادامه داده است. بسیاری از کد ناامن حذف شده است.

راکت

وجه تمایز

Rocket در میان چارچوب‌های وب Rust این است که به شما امکان می‌دهد بیشترین نتیجه را با کمترین کد دریافت کنید. نوشتن یک برنامه وب پایه در Rocket به خطوط نسبتا کمی و مراسم کمی نیاز دارد. Rocket این کار را با استفاده از سیستم نوع Rust برای توصیف بسیاری از رفتارها انجام می دهد، بنابراین می توان آنها را در زمان کامپایل اعمال و کدگذاری کرد.

در اینجا یک برنامه اولیه “Hello world” در Rocket آمده است:


#[macro_use] extern crate rocket;

#[get("/")]
fn hello_world() -> &'static str {
    "Hello, world!"
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![hello_world])
}

راکت از طریق استفاده از ویژگی‌ها بسیار کوتاه عمل می‌کند. مسیرها با ویژگی‌هایی برای روش‌ها و الگوهای URL که استفاده می‌کنند تزئین شده‌اند. همانطور که در این مثال مشاهده می کنید، ویژگی #[راه اندازی] عملکرد مورد استفاده برای نصب مسیرها و تنظیم برنامه برای گوش دادن به درخواست ها را نشان می دهد.

اگرچه مسیرهای مثال “سلام جهان” همزمان هستند، مسیرها می توانند در Rocket ناهمزمان باشند، و معمولاً باید در صورت امکان این مسیرها باشند. به طور پیش‌فرض، Rocket از زمان اجرا tokio برای رسیدگی به مواردی مانند تبدیل عملیات همگام‌سازی به غیر همگام‌سازی استفاده می‌کند.

Rocket بسیاری از ویژگی‌های معمول را برای رسیدگی به درخواست‌ها فراهم می‌کند – برای مثال استخراج متغیرها از عناصر URL. یکی از ویژگی‌های منحصربه‌فرد «حفاظ‌کنندگان درخواست» است، که در آن از انواع Rust استفاده می‌کنید که ویژگی FromRequest Rocket را برای توصیف خط‌مشی اعتبارسنجی برای یک مسیر پیاده‌سازی می‌کند.

به‌عنوان مثال، می‌توانید یک نوع سفارشی برای جلوگیری از شلیک مسیر ایجاد کنید، مگر اینکه اطلاعات خاصی در سرصفحه‌های درخواست وجود داشته باشد و قابل تأیید باشد – مانند یک کوکی با یک مجوز خاص مرتبط با آن. این به شما امکان می دهد مواردی مانند مجوزها را در ایمنی نوع کامپایل Rust بسازید.

یکی دیگر از ویژگی های مفید و متمایز Rocket fairings است، نسخه میان افزار Rocket. انواعی که ویژگی Fairing را اجرا می‌کنند، می‌توانند برای افزودن تماس‌های برگشتی به رویدادها، مانند درخواست‌ها یا پاسخ‌ها، استفاده شوند. اما فیرینگ ها نمی توانند درخواست ها را تغییر دهند یا متوقف کنند (اگرچه می توانند به نسخه هایی از داده های درخواست دسترسی داشته باشند).

برای این منظور، فیرینگ‌ها برای چیزهایی که رفتار جهانی دارند بهترین هستند – ثبت‌نام، جمع‌آوری معیارهای عملکرد، یا سیاست‌های امنیتی کلی. برای اقداماتی مانند احراز هویت، از محافظ درخواست استفاده کنید.

Warp

تمایز بزرگ

Warp از سایر چارچوب‌های وب Rust، روشی است که از مولفه‌های ترکیب‌پذیر – فیلترها استفاده می‌کند. “در زبان Warp—که می‌توانند برای ایجاد سرویس‌ها به هم متصل شوند.

مایکروسافت Hot Reload را به .NET SDK برمی گرداند

یک “سلام جهانی” اولیه در Warp این ویژگی را به‌خوبی نشان نمی‌دهد، اما ارزش این را دارد که نشان دهیم چارچوب چقدر می‌تواند مختصر باشد:


use warp::Filter;

#[tokio::main]
async fn main() {
    let hello = warp::path!().map(|| "Hello world");
    warp::serve(hello).run(([127, 0, 0, 1], 8080)).await;
}

فیلترها ویژگی Filter را پیاده‌سازی می‌کنند، هر فیلتر می‌تواند خروجی را به فیلتر دیگری برای اصلاح رفتارها ارسال کند. در این مثال، warp::path یک فایل‌کننده است که می‌توان آن را به عملیات‌های دیگر مانند .map() برای اعمال یک تابع زنجیره‌ای کرد.

مثال دیگری از مستندات Warp سیستم فیلتر را با جزئیات بیشتری نشان می دهد:


use warp::Filter;

let hi = warp::path("hello")
    .and(warp::path::param())
    .and(warp::header("user-agent"))
    .map(|param: String, agent: String| {
        format!("Hello {}, whose agent is {}", param, agent)
    });

در اینجا، چندین فیلتر به هم زنجیر شده اند تا رفتار زیر را به ترتیب ایجاد کنند:

  1. یک نقطه پایانی را با مسیر سلام تنظیم کنید.
  2. یک پارامتر به انتهای مسیر اضافه کنید، بنابراین مسیر باید به شکل /hello/ باشد. (روش .and() یکی از روش‌های کار ترکیب در Warp است.)
  3. یک تجزیه کننده برای سربرگ user-agent اضافه کنید، به طوری که هر درخواست ورودی بدون سرصفحه user-agent پردازش نشود.
  4. ماکرو format! را با پارامترهای param (پارامتر جمع‌آوری‌شده) و agent (user-agent string) به یک رشته، و آن را به مشتری برگردانید.

توسعه دهندگانی که به رویکرد ترکیبی علاقه دارند، دوست دارند که Warp چگونه روش کار آنها را تکمیل می کند.

یکی از نتایج رویکرد ترکیبی این است که شما می توانید یک کار را به روش های مختلف انجام دهید، نه همه آنها بصری. برای مشاهده راه‌های مختلف حل مشترک، ارزش دارد به نمونه‌های موجود در مخزن Warp نگاه کنید. سناریوهای برنامه نویسی با استفاده از Warp.

یک پیامد دیگر از نحوه عملکرد فیلترها در زمان کامپایل ناشی می شود. نوشتن مسیرهای زیادی از فیلترهای مختلف می تواند زمان کامپایل را طولانی تر کند، اگرچه مسیرها در زمان اجرا سریع هستند. گزینه دیگر استفاده از ارسال پویا برای سایت هایی با مسیرهای زیاد است که هزینه کمی برای عملکرد زمان اجرا دارد. یک مثال نحوه انجام این کار را با BoxedFilter نشان می‌دهد. نوع.

Axum

چارچوب Axum در بالای اکوسیستم جعبه برج برای مشتری ساخته می شود برنامه های سرور / از همه نوع، و همچنین tokio برای همگام سازی. اگر قبلاً با برج تجربه دارید یا از آن در پروژه‌های وابسته استفاده می‌کنید، استفاده از Axum را آسان‌تر می‌کند.

در اینجا یک برنامه اصلی Axum "hello world" در اسناد Axum وجود دارد. توجه داشته باشید که به نظر تفاوت چندانی با امثال Actix ندارد:


use axum::{
    routing::get,
    Router,
};

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(|| async { "Hello, World!" }));
    let listener = tokio::net::TcpListener::bind("127.0.0.1:8080").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Axum از بسیاری از الگوهای مشابه Actix برای نحوه عملکرد مسیرها و کنترلرها استفاده می کند. توابع Route-handler با روش .route() به یک شی Router اضافه می شوند و ماژول axum::extract دارای انواعی برای استخراج است. اجزای URL یا محموله های POST. پاسخ‌ها ویژگی IntoResponse را اجرا می‌کنند و خطاها از طریق نوع tower::Service Error خود tower رسیدگی می‌شوند. /p>

این آخرین رفتار، با تکیه بر برج برای مؤلفه‌های کلیدی Axum، همچنین شامل نحوه مدیریت میان‌افزار Axum نیز می‌شود. مسیریاب‌ها، متدها و کنترل‌کننده‌های فردی همگی می‌توانند از طریق روش‌های مختلف .layer در اشیاء tower از میان‌افزار استفاده کنند. همچنین می‌توان از tower::ServiceBuilder برای ایجاد مجموعه‌هایی از چندین لایه و اعمال آنها با هم استفاده کرد.

Axum ابزارهای خاص خود را برای سایر الگوهای رایج در خدمات وب فراهم می کند. به عنوان مثال، اشتراک‌گذاری وضعیت بین کنترل‌کننده‌ها، می‌تواند به روشی امن با نوع State انجام شود. راه‌هایی برای پیاده‌سازی سناریوهای معمولی مانند خاموش‌های دلپذیر< /a> یا تنظیم اتصال به پایگاه داده< /a> را می‌توانید در دایرکتوری نمونه‌های Axum پیدا کنید.

شعر

بیشتر زبان‌ها حداقل یک چارچوب وب با ویژگی‌های کامل و «حداکثری» (مانند جانگو در Python) و یک وب کوچک، مختصر و «مینیمالیستی» دارند. چارچوب (به عنوان مثال، بطری، دوباره در پایتون). شعر برای Rust در انتهای طیف قرار دارد و به‌طور پیش‌فرض ویژگی‌های کافی برای ایستادن را ارائه می‌کند. یک وب سرویس اولیه.

در اینجا یک مثال "سلام جهان" وجود دارد که نام کاربری را وقتی در URL گنجانده شده است تکرار می کند:


use poem::{get, handler, listener::TcpListener, web::Path, Route, Server};

#[handler]
fn hello(Path(name): Path<String>) -> String {
    format!("hello: {}", name)
}

#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
    let app = Route::new().at("/hello/:name", get(hello));
    Server::new(TcpListener::bind("0.0.0.0:3000"))
        .run(app)
        .await
}

بسیاری از ویژگی‌های این برنامه باید با چارچوب‌ها و نمونه‌هایی که تاکنون دیده‌اید آشنا باشد: راه‌اندازی مسیرها، اتصال URLها و کنترل‌کننده‌ها به آنها، استخراج عناصر از درخواست، و غیره.

>

برای پایین نگه داشتن زمان کامپایل، Poem به طور پیش‌فرض از ویژگی‌های خاص پشتیبانی نمی‌کند. /a>. کوکی‌ها، پیش‌بینی CSRF، HTTP از طریق TLS، WebSockets، بین‌المللی کردن، و فشرده‌سازی درخواست/پاسخ و فشرده‌سازی (به نام چند مورد) همه باید به صورت دستی فعال شوند.

با همه سادگی اش، Poem هنوز کاربردهای فراوانی دارد. این شامل مجموعه‌ای از میان‌افزارهای رایج و مفید است، و همچنین می‌توانید به راحتی خود را پیاده سازی کنید. یکی از سهولت های متفکر NormalizePath است، مکانیزمی برای سازگار کردن مسیرهای درخواست. این شامل یک کنترل کننده جهانی برای مدیریت اسلش های انتهایی در URL است. با کنترلر، می توانید قالب دلخواه خود را یک بار و به طور مداوم در سراسر برنامه پیاده سازی کنید.

دایرکتوری نمونه‌های Poem کوچک‌تر از برخی از چارچوب‌های دیگر است اینجا را مشاهده کرده‌اید، اما بیشتر بر روی نمونه‌هایی تمرکز می‌کند که به مستندات دقیق نیاز دارند - مانند استفاده از Poem با AWS Lambda، یا ایجاد APIهایی که مطابق با مشخصات OpenAPI هستند.

کدام چارچوب Rust برای شما بهترین است؟

Actix Web به طور کلی به عنوان یک راه حل خوب و متعادل عمل می کند، به خصوص اگر عملکرد یک هدف باشد. Rocket به شما امکان می دهد کد خود را کوتاه اما گویا نگه دارید و سیستم "fairings" آن استعاره قدرتمندی برای پیاده سازی رفتار میان افزار ارائه می دهد.

برنامه‌نویسانی که دوست دارند با عناصر ترکیب‌پذیر کار کنند، می‌خواهند Warp را امتحان کنند، زیرا به شما امکان می‌دهد مسیرها و گردش‌های کاری را به صورت برنامه‌نویسی با بیانی عالی بسازید. Axum مستقیماً برای کاربران Rust که قبلاً با اکوسیستم برج آشنا هستند جذابیت دارد، اما به اندازه کافی مفید است که محدود به آن مخاطب نیز نباشد. Poem به طور پیش‌فرض ساده است، و اگر تنها چیزی که نیاز دارید ابتدایی‌ترین مسیریابی و رسیدگی به درخواست‌ها باشد، عالی است. همچنین در صورت نیاز می‌توانید ویژگی‌های اضافی را نصب کنید.