Rust Web框架Actix插件paperclip-actix的使用:为RESTful API开发提供OpenAPI支持与自动化文档生成

Rust Web框架Actix插件paperclip-actix的使用:为RESTful API开发提供OpenAPI支持与自动化文档生成

安装

在项目目录中运行以下Cargo命令:

cargo add paperclip-actix

或者在Cargo.toml中添加以下行:

paperclip-actix = "0.7.3"

完整示例demo

以下是一个使用paperclip-actix为Actix-web应用添加OpenAPI支持和自动化文档生成的完整示例:

use actix_web::{web, App, HttpServer, Responder};
use paperclip::actix::{
    // 使用Apiv2Schema代替默认的serde::Serialize
    api_v2_operation,
    // 使用OpenApiExt扩展Actix-web应用
    OpenApiExt,
};

// 定义一个简单的结构体作为响应
#[derive(serde::Serialize, paperclip::actix::Apiv2Schema)]
struct HelloResponse {
    message: String,
}

// 使用api_v2_operation宏标记API操作
#[api_v2_operation]
async fn hello() -> impl Responder {
    web::Json(HelloResponse {
        message: "Hello, world!".to_string(),
    })
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            // 启用OpenAPI支持
            .wrap_api()
            // 添加API路由
            .service(
                web::resource("/hello")
                    .route(web::get().to(hello))
                    // 添加API文档元数据
                    .with_api_spec(|| {
                        paperclip::v2::models::Operation {
                            summary: Some("Say hello".to_string()),
                            description: Some("A simple hello endpoint".to_string()),
                            ..Default::default()
                        }
                    }),
            )
            // 添加Swagger UI
            .with_swagger_ui_at("/api/docs")
            // 构建Actix-web应用
            .build()
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

功能说明

  1. OpenAPI规范支持:通过wrap_api()方法启用OpenAPI支持
  2. 自动文档生成:使用with_swagger_ui_at()方法添加Swagger UI界面
  3. API元数据:使用with_api_spec()为路由添加描述信息
  4. Schema支持:使用Apiv2Schema派生宏为数据结构提供OpenAPI schema

运行和访问

  1. 启动应用程序后,查看Swagger UI界面
  2. API端点/hello将自动出现在文档中
  3. 可以交互式地测试API端点

注意事项

  • 确保所有响应类型都实现了Apiv2Schema trait
  • 使用api_v2_operation宏标记所有API处理函数
  • 可以通过with_api_spec()方法为路由添加更多元数据

1 回复

Rust Web框架Actix插件paperclip-actix使用指南

完整示例代码

下面是一个完整的paperclip-actix使用示例,集成了前面提到的各种功能:

use actix_web::{web, App, HttpResponse, HttpServer, Result};
use paperclip::actix::{
    api_v2_operation, 
    Apiv2Schema,
    OpenApiExt
};
use serde::{Serialize, Deserialize};

// 定义宠物数据结构
#[derive(Debug, Serialize, Deserialize, Apiv2Schema)]
struct Pet {
    id: u64,
    name: String,
    tag: Option<String>,
}

// 定义错误响应结构
#[derive(Debug, Serialize, Apiv2Schema)]
struct ErrorResponse {
    code: u32,
    message: String,
}

/// 获取所有宠物信息
///
/// 这个端点返回系统中所有的宠物信息列表
#[api_v2_operation(
    responses(
        (status = 200, description = "成功获取宠物列表", body = Vec<Pet>),
        (status = 500, description = "服务器内部错误", body = ErrorResponse)
    ),
    tags("pets")
)]
async fn get_pets() -> Result<web::Json<Vec<Pet>>, web::Json<ErrorResponse>> {
    Ok(web::Json(vec![
        Pet {
            id: 1,
            name: "Fluffy".into(),
            tag: Some("cat".into()),
        },
        Pet {
            id: 2,
            name: "Rex".into(),
            tag: Some("dog".into()),
        }
    ]))
}

/// 根据ID获取特定宠物信息
#[api_v2_operation(
    params(
        ("id" = u64, Path, description = "宠物ID")
    ),
    responses(
        (status = 200, description = "成功获取宠物信息", body = Pet),
        (status = 404, description = "宠物不存在", body = ErrorResponse)
    ),
    tags("pets")
)]
async fn get_pet_by_id(pet_id: web::Path<u64>) -> Result<web::Json<Pet>, web::Json<ErrorResponse>> {
    if *pet_id == 1 {
        Ok(web::Json(Pet {
            id: 1,
            name: "Fluffy".into(),
            tag: Some("cat".into()),
        }))
    } else {
        Err(web::Json(ErrorResponse {
            code: 404,
            message: "Pet not found".into(),
        }))
    }
}

/// 添加新宠物
#[api_v2_operation(
    security(
        ("api_key" = [])
    ),
    responses(
        (status = 201, description = "成功创建宠物", body = Pet),
        (status = 400, description = "无效输入", body = ErrorResponse)
    ),
    tags("pets")
)]
async fn add_pet(new_pet: web::Json<Pet>) -> Result<web::Json<Pet>, web::Json<ErrorResponse>> {
    Ok(web::Json(Pet {
        id: new_pet.id,
        name: new_pet.name.clone(),
        tag: new_pet.tag.clone(),
    }))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            // 启用Paperclip
            .wrap_api()
            // 配置OpenAPI规范路径
            .with_json_spec_at("/api/spec")
            // 配置Swagger UI路径和自定义设置
            .with_swagger_ui_at_with_config("/docs", {
                let mut conf = paperclip::actix::SwaggerUIConfig::default();
                conf.default_models_expand_depth = -1; // 默认折叠所有模型
                conf
            })
            // 注册路由
            .service(
                web::resource("/pets")
                    .route(web::get().to(get_pets))
                    .route(web::post().to(add_pet))
            )
            .service(
                web::resource("/pets/{id}")
                    .route(web::get().to(get_pet_by_id))
            )
            .build()
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

示例说明

  1. 数据结构:

    • 定义了PetErrorResponse结构体,并实现了Apiv2Schema trait
    • 使用SerializeDeserialize来自动序列化/反序列化
  2. API端点:

    • get_pets: 获取所有宠物列表
    • get_pet_by_id: 根据ID获取特定宠物
    • add_pet: 添加新宠物
  3. 文档生成:

    • 使用#[api_v2_operation]宏添加操作文档
    • 包含响应状态码描述、参数描述和标签
    • 添加了安全定义(api_key)
  4. Swagger UI配置:

    • 自定义UI配置,默认折叠所有模型
    • 规范JSON位于/api/spec
    • Swagger UI位于/docs
  5. 错误处理:

    • 定义了统一的错误响应结构
    • 每个端点都明确定义了可能的错误响应

这个完整示例展示了如何使用paperclip-actix创建一个有完整文档支持的RESTful API服务,包含了参数文档、响应模型、错误处理和Swagger UI集成等功能。

回到顶部