Swagger/OpenAPI генерация для Rust: библиотека Utoipa

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Swagger/OpenAPI генерация для Rust: Utoipa — современный инструмент для автоматической документации

При разработке веб-приложений на Rust документация API — не роскошь, а необходимость. Библиотека Utoipa (сокращение от "Utopia") предоставляет мощный и элегантный способ генерации OpenAPI спецификаций прямо из кода. Она интегрируется с популярными веб-фреймворками, такими как actix-web, axum, rocket и warp, и позволяет описывать эндпоинты, схемы данных и параметры с помощью атрибутов и макросов.

Основные возможности Utoipa

  • Автоматическая генерация OpenAPI 3.0/3.1 — без ручного написания YAML/JSON.
  • Поддержка множества фреймворков — actix-web, axum, rocket, warp.
  • Интеграция с Swagger UI — встроенный компонент для визуализации документации.
  • Глубокое описание схем — поддержка вложенных структур, перечислений, опциональных полей.
  • Макросы для быстрого описания — #[utoipa::path], #[openapi].
  • Валидация спецификации — проверка корректности сгенерированного документа.

Установка и настройка

Добавьте зависимости в Cargo.toml. Для примера выберем фреймворк actix-web:

[dependencies]
utoipa = "4"
utoipa-swagger-ui = { version = "4", features = ["actix-web"] }
actix-web = "4"
serde = { version = "1", features = ["derive"] }

Базовый пример: создание API с документацией

Рассмотрим простой CRUD для сущности "Пользователь". Начнём с определения модели данных:

use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

#[derive(Serialize, Deserialize, ToSchema)]
pub struct User {
    #[schema(example = "1")]
    pub id: i32,
    #[schema(example = "john_doe")]
    pub username: String,
    #[schema(example = "john@example.com")]
    pub email: String,
}

Теперь опишем эндпоинт получения списка пользователей с помощью макроса #[utoipa::path]:

use actix_web::{get, web, HttpResponse, Responder};
use utoipa::OpenApi;

#[utoipa::path(
    get,
    path = "/users",
    responses(
        (status = 200, description = "Список пользователей", body = Vec<User>)
    )
)]
#[get("/users")]
async fn get_users() -> impl Responder {
    let users = vec![
        User { id: 1, username: "alice".into(), email: "alice@example.com".into() },
        User { id: 2, username: "bob".into(), email: "bob@example.com".into() },
    ];
    HttpResponse::Ok().json(users)
}

Сборка OpenAPI документа и Swagger UI

Создаём структуру для описания всего API:

#[derive(OpenApi)]
#[openapi(
    paths(get_users),
    components(schemas(User))
)]
pub struct ApiDoc;

// В main функции настраиваем Swagger UI
use utoipa_swagger_ui::SwaggerUi;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    use actix_web::App;

    HttpServer::new(|| {
        App::new()
            .service(get_users)
            .service(
                SwaggerUi::new("/swagger-ui/{_:.*}")
                    .url("/api-docs/openapi.json", ApiDoc::openapi())
            )
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

После запуска приложения документация будет доступна по адресу http://localhost:8080/swagger-ui/.

Продвинутые возможности: вложенные схемы и параметры

Utoipa поддерживает сложные типы данных. Например, добавим поле с вложенной структурой:

#[derive(Serialize, Deserialize, ToSchema)]
pub struct Address {
    #[schema(example = "г. Москва")]
    pub city: String,
    #[schema(example = "ул. Ленина, д. 1")]
    pub street: String,
}

#[derive(Serialize, Deserialize, ToSchema)]
pub struct UserWithAddress {
    pub id: i32,
    pub username: String,
    pub address: Address, // вложенная схема
}

Также можно описывать параметры пути и query-параметры:

#[utoipa::path(
    get,
    path = "/users/{id}",
    params(
        ("id" = i32, Path, description = "Идентификатор пользователя                    

Рекомендаций