Перейти к содержанию

Введение в Actix - Rust Web Framework

Posted on:3 июля 2023 г. at 08:27

Example Dynamic OG Image link Actix - это надежная, прагматичная, быстрая структура Rust для создания веб-приложений. Он использует модель актора для управления состоянием и параллелизмом, заимствуя из философии языка Erlang. Actix также основан на небольшой, простой в использовании акторной системе, обеспечивающей более чистый и интуитивно понятный интерфейс.

Actix web построен поверх Actix, высокопроизводительной, гибкой и удобной в использовании структуры акторов общего назначения. Actix web предоставляет инструменты и библиотеки для создания HTTP-серверов и веб-приложений.

Преимущества Actix Web

  1. Производительность: Actix web разработан, чтобы быть легким и быстрым. Это один из самых быстрых веб-фреймворков, доступных на любом языке программирования.
  2. Безопасность: Actix и Rust уделяют большое внимание безопасности типа, безопасности памяти и параллелизму, что означает, что ваш код будет эффективным и безопасным от распространенных ошибок программирования.
  3. Асинхронность: Actix Web поддерживает асинхронные обработчики запросов, что делает его идеальным для программирования веб-приложений, требующих обработки многих параллельных соединений, таких как в реальном времени или микросервисы.
  4. Система промежуточного программного обеспечения: Actix предлагает мощную систему промежуточного программного обеспечения, позволяющую разработчикам расширять и изменять конвейер обработки запросов-ответов.
  5. Расширяемый: Он имеет надежный набор модулей и библиотек для обработки сеансов, обработки форм, обработки файлов, cookie, тестирования и т.д., что делает процесс разработки простым и эффективным.

Внедрение CRUD RESTful с помощью Actix Web

Мы внедрим простой API управления книгами, позволяющий создавать, читать, обновлять и удалять книги.

Установка

Перед началом работы необходимо установить Rust и Actix. Скачать Rust можно с официального сайта.

Создание нового проекта с помощью:

cargo new book_manager
cd book_manager

В файле Cargo.toml добавьте следующие зависимости:

[dependencies]
actix-web = "3"
serde = { version = "1", features = ["derive"] }

Определение модели

Начнем с определения структуры нашей книги в src/main.rs:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct Book {
    id: u32,
    title: String,
    author: String,
}

Создание роутеров

Теперь давайте определим наши роутеры. Сейчас мы настроим наш HTTP-сервер и создадим обработчики заглушек для каждой операции CRUD.

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

async fn create_book(_book: web::Json<Book>) -> impl Responder {
    HttpResponse::Ok().json("Create book")
}

async fn read_book(_id: web::Path<u32>) -> impl Responder {
    HttpResponse::Ok().json("Read book")
}

async fn update_book(_id: web::Path<u32>, _book: web::Json<Book>) -> impl Responder {
    HttpResponse::Ok().json("Update book")
}

async fn delete_book(_id: web::Path<u32>) -> impl Responder {
    HttpResponse::Ok().json("Delete book")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/books", web::post().to(create_book))
            .route("/books/{id}", web::get().to(read_book))
            .route("/books/{id}", web::put().to(update_book))
            .route("/books/{id}", web::delete().to(delete_book))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Это приведет к установке сервера на локальном порту 8080 и обработке операций CRUD в различных конечных точках. web::Json и web::Path - это типы экстракторов, извлекающих данные из тела или пути запроса.

Внедрение обработчиков

Для простоты мы будем использовать простую HashMap в качестве нашей базы данных:

use std::collections::HashMap;
use std::sync::Mutex;
use actix_web::{web, App, HttpServer, Responder, HttpResponse};
use std::sync::Arc;

struct AppState {
    books: Mutex<HashMap<u32, Book>>,
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let shared_data = web::Data::new(AppState {
        books: Mutex::new(HashMap::new()),
    });

    HttpServer::new(move || {
        App::new()
            .app_data(shared_data.clone())
            .route("/books", web::post().to(create_book))
            .route("/books/{id}", web::get().to(read_book))
            .route("/books/{id}", web::put().to(update_book))
            .route("/books/{id}", web::delete().to(delete_book))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Теперь мы можем реализовать наши обработчики:

async fn create_book(book: web::Json<Book>, data: web::Data<AppState>) -> impl Responder {
    let mut books = data.books.lock().unwrap();
    books.insert(book.id, book.into_inner());
    HttpResponse::Ok().json("Created book")
}

async fn read_book(id: web::Path<u32>, data: web::Data<AppState>) -> impl Responder {
    let books = data.books.lock().unwrap();
    match books.get(&id.into_inner()) {
        Some(book) => HttpResponse::Ok().json(book),
        None => HttpResponse::NotFound().json("Book not found"),
    }
}

async fn update_book(id: web::Path<u32>, book: web::Json<Book>, data: web::Data<AppState>) -> impl Responder {
    let mut books = data.books.lock().unwrap();
    if books.contains_key(&id.into_inner()) {
        books.insert(book.id, book.into_inner());
        HttpResponse::Ok().json("Updated book")
    } else {
        HttpResponse::NotFound().json("Book not found")
    }
}

async fn delete_book(id: web::Path<u32>, data: web::Data<AppState>) -> impl Responder {
    let mut books = data.books.lock().unwrap();
    match books.remove(&id.into_inner()) {
        Some(_) => HttpResponse::Ok().json("Deleted book"),
        None => HttpResponse::NotFound().json("Book not found"),
    }
}

Это создаст базовый API с операциями CRUD. Обратите внимание, что это простой пример, и в реальном приложении необходимо использовать реальную базу данных, более корректно обрабатывать ошибки и добавлять аутентификацию.

Подробнее об Actix

Хотя приведенный выше пример иллюстрирует простой вариант использования, Actix может обрабатывать более сложные сценарии. Он поддерживает различные формы связи, такие как WebSockets и события, отправляемые сервером (SSE). Кроме того, Actix обеспечивает широкую поддержку промежуточного программного обеспечения, позволяя расширять и настраивать конвейеры запрос-ответ.

Промежуточное программное обеспечение в Actix

Компоненты промежуточного программного обеспечения в Actix - это многоразовые программные компоненты, которые могут обрабатывать запросы и ответы, изменять их и выполнять различные операции, такие как ведение журнала, аутентификация, управление сеансами и т.д.

Создание промежуточного программного обеспечения в Actix Web так же просто, как и реализация трейта промежуточного программного обеспечения для компонента. После этого можно добавить промежуточное программное обеспечение в приложение с помощью обертки или wrap_fn.

Тестирование в Actix

Actix предоставляет тестовый модуль для записи модульных тестов для вашего приложения. Он включает в себя TestServer и функцию call_service, которая имитирует HTTP-клиент для тестирования функциональных возможностей приложения.

#[actix_rt::test]
async fn test_read_book() {
    let mut app = test::init_service(App::new().route("/books/{id}", web::get().to(read_book))).await;
    let req = test::TestRequest::get().uri("/books/1").to_request();
    let resp = test::call_service(&mut app, req).await;
    assert!(resp.status().is_success());
}

Это базовый тест для проверки правильности работы маршрута /books/{ id}. Реальное тестирование будет включать более сложные сценарии, включая проверку соответствия возвращенного ответа ожидаемому результату.

Интеграция Actix с базами данных

Actix, будучи веб-платформой, не поддерживает базы данных напрямую. Тем не менее, обычно базы данных используются в веб-службе, и у Rust есть несколько библиотек для работы с базами данных, например Diesel и SQLx. Они могут быть легко интегрированы с Actix Web для создания полноценных веб-сервисов.

Обработка ошибок

Обработка ошибок имеет решающее значение для любого веб-приложения. В Actix тип Result обычно используется для возврата и распространения ошибок. Если в обработчике возникает ошибка, Actix прекращает обработку и возвращает клиенту ошибку сервера.

В заключение

Actix - это мощная, безопасная и эффективная платформа для создания веб-приложений в Rust. Он сочетает акцент Rust на абстракции с нулевыми затратами и безопасность памяти с прагматичным, простым в использовании подходом к разработке веб-сервисов.

Его конструкция на основе акторов обеспечивает чистый и интуитивный подход к управлению состоянием и обработке параллелизма. В то же время его обширная поддержка промежуточного программного обеспечения и интеграция с другими библиотеками Rust позволяют создавать надежные веб-приложения с широкими возможностями. Независимо от того, являетесь ли вы новичком в Rust или опытным разработчиком, Actix предлагает отличный вариант для веб-разработки.