Настройка проекта
Структура API
«Настройка проекта» — бесплатный урок Learn Rust Coding на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Learn Rust Coding, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Learn Rust Coding содержит 4 уроков всего.
Создание REST API на Rust
В этом курсе Вы создадите небольшое REST API на Rust. Мы используем веб-фреймворк Axum, построенный на Tokio (асинхронной среде выполнения) и Tower (промежуточном программном обеспечении). Он удобен, безопасен с точки зрения типов и широко используется в промышленной разработке.
В этом первом уроке создаётся структура проекта, чтобы в следующих уроках можно было добавить маршруты, модели, базу данных и тесты.
Создание проекта
Начните с Cargo. Бинарный проект предоставляет точку входа src/main.rs:
cargo new rest_apiсоздаёт папку.cd rest_apiпереходит в неё.cargo runсобирает и запускает проект.
Это команды оболочки и Cargo, а не запускаемые фрагменты Rust.
// terminal
// cargo new rest_api
// cd rest_api
// cargo runДобавление зависимостей
Для API на Axum нужны несколько ящиков в Cargo.toml:
axum— для маршрутизации и обработчиков.tokio— для асинхронной среды выполнения.serde— для сериализации JSON.
// Cargo.toml
// [dependencies]
// axum = "0.7"
// tokio = { version = "1", features = ["full"] }
// serde = { version = "1", features = ["derive"] }
// serde_json = "1"Асинхронная среда выполнения
Веб-серверы одновременно обрабатывают множество подключений, поэтому Axum является асинхронным. Атрибут #[tokio::main] превращает асинхронную main в настоящую точку входа, запуская среду выполнения Tokio. Каждый обработчик может использовать .await для неблокирующего ввода-вывода.
// src/main.rs
use tokio;
#[tokio::main]
async fn main() {
println!("runtime started");
}Минимальный сервер
Самое маленькое приложение Axum создаёт Router, привязывает TCP-слушатель и запускает обслуживание. Один маршрут связывает GET / с обработчиком, возвращающим строку. Обработчики — это обычные асинхронные функции, возвращающие значение, реализующее IntoResponse.
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(root));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn root() -> &'static str {
"Hello, API!"
}Как работает маршрутизация
Router связывает путь и HTTP-метод с обработчиком. Цепочкой вызовов .route(path, method(handler)) регистрируйте конечные точки. Вспомогательные функции методов, такие как get, post, put и delete, находятся в axum::routing. Можно объединять несколько методов для одного пути.
use axum::{routing::{get, post}, Router};
async fn list() -> &'static str { "list" }
async fn create() -> &'static str { "created" }
fn build_router() -> Router {
Router::new()
.route("/items", get(list).post(create))
.route("/health", get(|| async { "ok" }))
}Рекомендуемая структура модулей
По мере роста API разделяйте код на модули, а не храните всё в одном огромном main.rs:
main.rs— запуск и настройка сервера.routes.rs— определение маршрутизатора.handlers.rs— обработчики запросов.models.rs— структуры данных.
Такое разделение позволяет сосредоточить каждый файл на одной задаче и упростить его тестирование.
// src/main.rs
mod routes;
mod handlers;
mod models;
#[tokio::main]
async fn main() {
let app = routes::build();
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await.unwrap();
axum::serve(listener, app).await.unwrap();
}Общее состояние приложения
Большинству API требуется общее состояние, например пул подключений к базе данных или хранилище в памяти. Axum хранит его в маршрутизаторе с помощью .with_state(state). Обработчики получают его через извлекатель State. Состояние должно поддерживать Clone; изменяемые данные следует обернуть в Arc и блокировку.
use axum::{routing::get, Router, extract::State};
use std::sync::{Arc, Mutex};
type Db = Arc<Mutex<Vec<String>>>;
async fn count(State(db): State<Db>) -> String {
let n = db.lock().unwrap().len();
format!("{} items", n)
}
fn build(db: Db) -> Router {
Router::new().route("/count", get(count)).with_state(db)
}Возврат JSON
Чтобы отправить JSON, оберните сериализуемое значение в axum::Json. Если с помощью serde вывести Serialize для Ваших структур, Axum автоматически установит правильный тип содержимого и тело ответа.
use axum::Json;
use serde::Serialize;
#[derive(Serialize)]
struct Status {
service: String,
healthy: bool,
}
async fn health() -> Json<Status> {
Json(Status { service: "api".into(), healthy: true })
}Конфигурация и порты
Жёстко заданный порт подходит для демонстраций, но реальные службы считывают конфигурацию из окружения. Используйте std::env::var со значением по умолчанию. Это позволяет менять адрес привязки без повторной сборки и удобно работать с контейнерами.
use std::env;
async fn main_inner() {
let port = env::var("PORT").unwrap_or_else(|_| "3000".to_string());
let addr = format!("0.0.0.0:{}", port);
println!("binding to {}", addr);
// bind and serve with addr ...
}Объединение настройки
Полная настройка включает всё необходимое: создать маршрутизатор с маршрутами и общим состоянием, прочитать порт, привязать слушатель и запустить обслуживание. Теперь, когда каркас готов, в следующих уроках можно добавить настоящие конечные точки, модели и сохранение данных.
use axum::{routing::get, Router};
use std::sync::{Arc, Mutex};
#[tokio::main]
async fn main() {
let db = Arc::new(Mutex::new(Vec::<String>::new()));
let app = Router::new()
.route("/health", get(|| async { "ok" }))
.with_state(db);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await.unwrap();
axum::serve(listener, app).await.unwrap();
}Быстрая проверка
Проверьте, насколько хорошо Вы понимаете настройку проекта.
Итоги
Вы настроили проект REST API на Rust:
- Используйте
cargo newи добавьтеaxum,tokioиserde. #[tokio::main]предоставляет асинхронную среду выполнения.Routerсвязывает пути и методы с асинхронными обработчиками.- Делитесь данными с помощью
.with_stateи извлекателяState. - Разделяйте код на модули маршрутов, обработчиков и моделей; считывайте порт из окружения.
Часто задаваемые вопросы
Урок «Настройка проекта» бесплатный?
Да — полный текст урока «Настройка проекта» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Learn Rust Coding, подпишись на CoddyKit PRO. Курс Learn Rust Coding содержит 4 уроков всего.
Чему я научусь в уроке «Настройка проекта»?
Структура API Ты практикуешь Learn Rust Coding с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Learn Rust Coding?
Предыдущий опыт не требуется. Learn Rust Coding на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Настройка проекта»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Learn Rust Coding?
Да. Каждый урок Learn Rust Coding включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Настройка проекта
- Конечные точки и модели
- Интеграция с базой данных
- Тестирование API