| Crates.io | oxidite-openapi |
| lib.rs | oxidite-openapi |
| version | 2.0.1 |
| created_at | 2025-12-07 14:48:42.007641+00 |
| updated_at | 2026-01-25 01:47:40.259484+00 |
| description | OpenAPI/Swagger documentation generation for Oxidite |
| homepage | |
| repository | https://github.com/meshackbahati/rust-oxidite |
| max_upload_size | |
| id | 1971717 |
| size | 20,782 |
OpenAPI/Swagger documentation generation for the Oxidite web framework.
oxidite-openapi provides automatic OpenAPI/Swagger documentation generation for Oxidite web applications. It allows you to generate comprehensive API documentation that follows the OpenAPI specification, making it easy for developers to understand and consume your APIs.
Add this to your Cargo.toml:
[dependencies]
oxidite-openapi = "0.2.0"
Add OpenAPI documentation to your Oxidite application:
use oxidite::prelude::*;
use oxidite_openapi::{OpenApiSpec, OpenApiBuilder};
#[tokio::main]
async fn main() -> Result<()> {
let mut router = Router::new();
// Add your routes
router.get("/users", get_users);
router.post("/users", create_user);
router.get("/users/:id", get_user);
// Build OpenAPI specification
let spec = OpenApiBuilder::new()
.title("My API")
.version("1.0.0")
.description("My awesome API built with Oxidite")
.contact_name("API Support")
.contact_email("support@example.com")
.license_name("MIT")
.build();
// Add route to serve OpenAPI spec
router.get("/openapi.json", move |_| async move {
Ok(response::json(spec.clone()))
});
Server::new(router)
.listen("127.0.0.1:3000".parse().unwrap())
.await
}
Document your API endpoints with detailed information:
use oxidite::prelude::*;
use oxidite_openapi::{EndpointDoc, Parameter, Response};
// Document a GET endpoint
#[EndpointDoc(
summary = "Get all users",
description = "Returns a list of all users in the system",
parameters = [
Parameter::query("page", "integer", "Page number", Some("1")),
Parameter::query("limit", "integer", "Items per page", Some("10"))
],
responses = [
Response::ok("List of users", "Vec<User>"),
Response::bad_request("Invalid parameters")
]
)]
async fn get_users(
Query(params): Query<PaginationParams>,
State(db): State<Database>
) -> Result<OxiditeResponse> {
let users = User::all(&db).limit(params.limit).offset((params.page - 1) * params.limit).await?;
Ok(response::json(users))
}
// Document a POST endpoint
#[EndpointDoc(
summary = "Create a new user",
description = "Creates a new user in the system",
request_body = "CreateUserRequest",
responses = [
Response::created("User created", "User"),
Response::conflict("User already exists"),
Response::unprocessable_entity("Validation error")
]
)]
async fn create_user(
Json(payload): Json<CreateUserRequest>,
State(db): State<Database>
) -> Result<OxiditeResponse> {
// Validate payload
if !is_valid_email(&payload.email) {
return Err(OxiditeError::Validation("Invalid email format".to_string()));
}
let user = User {
id: 0,
name: payload.name,
email: payload.email,
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
};
user.create(&db).await?;
Ok(response::json(user).status(http::StatusCode::CREATED))
}
Define schemas for your API models:
use oxidite_openapi::Schema;
#[derive(Serialize, Deserialize, Schema)]
pub struct User {
/// Unique identifier for the user
pub id: i64,
/// User's full name
pub name: String,
/// User's email address
pub email: String,
/// Timestamp when the user was created
pub created_at: chrono::DateTime<chrono::Utc>,
/// Timestamp when the user was last updated
pub updated_at: chrono::DateTime<chrono::Utc>,
}
#[derive(Serialize, Deserialize, Schema)]
pub struct CreateUserRequest {
/// User's full name (required)
#[schema(min_length = 1, max_length = 100)]
pub name: String,
/// User's email address (required)
#[schema(pattern = r"^[^@]+@[^@]+\.[^@]+$")]
pub email: String,
}
Document authentication and authorization:
use oxidite_openapi::{SecurityScheme, ApiKeyLocation};
let spec = OpenApiBuilder::new()
.title("My API")
.version("1.0.0")
// Add API key security scheme
.security_scheme(
"api_key",
SecurityScheme::ApiKey {
name: "X-API-Key".to_string(),
location: ApiKeyLocation::Header,
description: Some("API key for authentication".to_string()),
}
)
.build();
Serve the interactive Swagger UI with your documentation:
use oxidite::prelude::*;
use oxidite_openapi::{OpenApiSpec, SwaggerUi};
async fn setup_swagger_ui(router: &mut Router) {
// First, generate your OpenAPI spec
let spec = generate_openapi_spec();
// Add the spec endpoint
router.get("/openapi.json", move |_| async move {
Ok(response::json(spec.clone()))
});
// Add Swagger UI
let swagger_ui = SwaggerUi::new("/swagger-ui/")
.spec_url("/openapi.json")
.title("My API - Swagger UI");
// Register Swagger UI routes
router.get("/swagger-ui/", swagger_ui.handler());
router.get("/swagger-ui/*", swagger_ui.handler());
}
Fine-tune your API documentation:
use oxidite_openapi::{EndpointDoc, Parameter, Response, Schema};
#[EndpointDoc(
operation_id = "get_user_by_id",
summary = "Get user by ID",
description = "Retrieve a specific user by their unique identifier",
tags = ["users"],
parameters = [
Parameter::path("id", "integer", "User ID"),
],
responses = [
Response::ok("User details", "User"),
Response::not_found("User not found"),
],
deprecated = false
)]
async fn get_user(
Path(params): Path<UserId>,
State(db): State<Database>
) -> Result<OxiditeResponse> {
match User::find(&db, params.id).await? {
Some(user) => Ok(response::json(user)),
None => Err(OxiditeError::NotFound("User not found".to_string())),
}
}
Validate your OpenAPI specification:
use oxidite_openapi::OpenApiValidator;
#[tokio::test]
async fn test_openapi_spec_validity() {
let spec = generate_openapi_spec();
// Validate the specification
let validator = OpenApiValidator::new();
let result = validator.validate(&spec);
assert!(result.is_valid(), "OpenAPI spec should be valid");
// Check for specific issues
for warning in result.warnings() {
eprintln!("Warning: {}", warning);
}
}
The OpenAPI integration works seamlessly with Oxidite's architecture:
use oxidite::prelude::*;
use oxidite_openapi::OpenApiBuilder;
async fn create_documented_app() -> Router {
let mut router = Router::new();
// Add your API routes
router.get("/api/users", get_users);
router.post("/api/users", create_user);
router.get("/api/users/:id", get_user);
router.put("/api/users/:id", update_user);
router.delete("/api/users/:id", delete_user);
// Generate OpenAPI documentation
let spec = OpenApiBuilder::new()
.title("User Management API")
.version("1.0.0")
.description("API for managing users")
.server("https://api.example.com", "Production server")
.server("https://staging-api.example.com", "Staging server")
.build();
// Add documentation endpoints
router.get("/api/openapi.json", move |_| async move {
Ok(response::json(spec.clone()))
});
// Add a catch-all for API docs
router.get("/api/docs", |_req| async move {
Ok(response::html(include_str!("../docs/swagger.html")))
});
router
}
MIT