Введение: почему Rust для REST API?
Rust — это современный системный язык программирования, который сочетает в себе производительность C/C++ и безопасность памяти без сборщика мусора. Для создания REST API Rust предлагает несколько мощных фреймворков, и Actix-web — один из самых популярных. В этом руководстве мы шаг за шагом создадим полноценный REST API на Rust за 30 минут. Вы увидите, как быстро можно начать, даже если вы новичок в Rust.
Подготовка окружения
Прежде чем писать код, убедитесь, что у вас установлен Rust. Если нет — выполните команду:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
После установки проверьте версию:
rustc --version
Теперь создайте новый проект:
cargo new rust_rest_api
cd rust_rest_api
Откройте файл Cargo.toml и добавьте зависимости:
[dependencies]
actix-web = "4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1", features = ["full"] }
Запустите cargo build, чтобы установить все пакеты. Это займёт 1–2 минуты.
Создание базового REST API на Rust
Начнём с простого эндпоинта, который возвращает приветствие. Откройте src/main.rs и напишите:
use actix_web::{web, App, HttpServer, Responder};
async fn hello() -> impl Responder {
"Привет, мир! Это REST API на Rust!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Сервер запущен на http://127.0.0.1:8080");
HttpServer::new(|| {
App::new()
.route("/", web::get().to(hello))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Запустите сервер командой cargo run и откройте в браузере http://127.0.0.1:8080. Вы увидите наше приветствие. Это основа любого REST API на Rust.
Добавление структуры данных и JSON
Настоящее REST API работает с JSON. Создадим модель пользователя и эндпоинт для его получения:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct User {
id: u32,
name: String,
email: String,
}
async fn get_user() -> impl Responder {
let user = User {
id: 1,
name: "Иван Петров".to_string(),
email: "ivan@example.com".to_string(),
};
web::Json(user)
}
// В main() добавьте новый маршрут:
// .route("/user", web::get().to(get_user))
Теперь по адресу /user вы получите JSON-объект. Это ключевой момент: Rust автоматически сериализует структуру в JSON благодаря serde.
Работа с параметрами запроса и POST-запросами
Настоящее API должно обрабатывать разные HTTP-методы и параметры. Добавим эндпоинт для создания пользователя через POST:
use actix_web::web::Json;
async fn create_user(user: Json<User>) -> impl Responder {
let new_user = user.into_inner();
println!("Создан пользователь: {} ({})", new_user.name, new_user.email);
web::Json(new_user)
}
// В main():
// .route("/user", web::post().to(create_user))
Теперь можно отправить POST-запрос с телом JSON, например, через curl:
curl -X POST http://127.0.0.1:8080/user \
-H "Content-Type: application/json" \
-d '{"id":2,"name":"Мария Смирнова","email":"maria@example.com"}'
Сервер вернёт тот же объект, подтверждая создание. Это основа для CRUD-операций.
Обработка параметров пути и строки запроса
Добавим эндпоинт для получения пользователя по ID через параметр пути:
use actix_web::web::Path;
async fn get_user_by_id(path: Path<u32>) -> impl Responder {
let user_id = path.into_inner();
// В реальном приложении здесь был бы запрос к БД
let user = User {
id: user_id,
name: format!("Пользователь {}", user_id),
email: format!("user{}@example.com", user_id),
};
web::Json(user)
}
// В main():
// .route("/user/{id}", web::get().to(get_user_by_id))
Теперь http://127.0.0.1:8080/user/42 вернёт пользователя с ID 42. Для обработки query-параметров используйте web::Query:
use actix_web::web::Query;
#[derive(Deserialize)]
struct UserQuery {
name: Option<String>,
limit: Option<u32>,
}
async fn search_users(query: Query<UserQuery>) -> impl Responder {
let name = query.name.clone().unwrap_or_default();
let limit = query.limit.unwrap_or(10);
web::Json(format!("Поиск пользователей: имя={}, лимит={}", name, limit))
}
// В main():
// .route("/users/search", web::get().to(search_users))
Добавление CORS и обработка ошибок
Для работы с фронтендом нужно настроить CORS. Добавьте в Cargo.toml:
actix-cors = "0.7"
И обновите main.rs:
use actix_cors::Cors;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
let cors = Cors::default()
.allow_any_origin()
.allow_any_method()
.allow_any_header();
App::new()
.wrap(cors)
.route("/", web::get().to(hello))
.route("/user", web::get().to(get_user))
.route("/user", web::post().to(create_user))
.route("/user/{id}", web::get().to(get_user_by_id))
.route("/users/search", web::get().to(search_users))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Для обработки ошибок используйте Http