### Conventional Commit Message Example Source: https://github.com/tamasfe/aide/blob/master/CONTRIBUTING.md Example of a conventional commit message for adding a new feature to the 'aide' crate. This format is used for automated changelog generation. ```markdown feat(aide): added new feature ``` -------------------------------- ### Rust: Configure API Router with Nested Routes and State using aide Source: https://context7.com/tamasfe/aide/llms.txt This snippet demonstrates how to set up an API router in Rust using the aide and axum crates. It includes defining shared application state, handling GET requests for posts by ID and listing all posts, and nesting routes under a common path. Dependencies include aide, axum, schemars, serde, and tokio. ```rust use aide::axum::{routing::get_with, ApiRouter}; use axum::extract::{Path, State}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::sync::Arc; use tokio::sync::Mutex; #[derive(Clone)] struct AppState { db: Arc>> } #[derive(Clone, Serialize, Deserialize, JsonSchema)] struct Post { id: u64, title: String, content: String, } async fn get_post( State(state): State, Path(id): Path, ) -> aide::axum::IntoApiResponse { let db = state.db.lock().await; match db.iter().find(|p| p.id == id) { Some(post) => axum::Json(post.clone()).into_response(), None => axum::http::StatusCode::NOT_FOUND.into_response(), } } async fn list_posts(State(state): State) -> aide::axum::IntoApiResponse { let db = state.db.lock().await; axum::Json(db.clone()).into_response() } fn post_routes(state: AppState) -> ApiRouter { ApiRouter::new() .api_route_with( "/", get_with(list_posts, |op| { op.description("List all posts") .tag("posts") .response::<200, axum::Json>>() }), |path| path.tag("posts"), ) .api_route_with( "/{id}", get_with(get_post, |op| { op.description("Get a single post by ID") .tag("posts") .response::<200, axum::Json>() .response_with::<404, (), _>(|res| { res.description("Post not found") }) }), |path| path.tag("posts"), ) .with_state(state) } fn build_app() -> ApiRouter { let state = AppState { db: Arc::new(Mutex::new(vec![ Post { id: 1, title: "First Post".into(), content: "Content here".into(), }, ])), }; ApiRouter::new() .nest_api_service("/posts", post_routes(state.clone())) .with_state(state) } ``` -------------------------------- ### Handler Function Using Custom Extractor and Response (Rust) Source: https://context7.com/tamasfe/aide/llms.txt An example handler function `search_handler` that utilizes the custom `CustomQuery` extractor and returns a `CustomResponse`. This demonstrates how custom input and output types, when properly implemented with aide's traits, integrate seamlessly into Axum handlers and contribute to automatic API documentation. ```rust async fn search_handler(query: CustomQuery) -> CustomResponse> { CustomResponse { data: vec!["result1".into(), "result2".into()], meta: [("count".into(), "2".into())].into(), } } ``` -------------------------------- ### Axum Integration for OpenAPI Generation in Rust Source: https://context7.com/tamasfe/aide/llms.txt This Rust code demonstrates how to integrate Aide with the Axum web framework to automatically generate OpenAPI documentation. It defines user creation schemas and handler functions, applies documentation transforms, and serves the OpenAPI JSON specification. Dependencies include `aide`, `axum`, `schemars`, `serde`, and `tokio`. ```rust use aide:: axum:: routing::{get, post_with}, ApiRouter, IntoApiResponse, }, openapi::{OpenApi, Tag}, transform::TransformOpenApi, }; use axum:: Extension, Json ; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::sync::Arc; #[derive(Deserialize, JsonSchema)] struct CreateUser { name: String, email: String, } #[derive(Serialize, JsonSchema)] struct User { id: u64, name: String, email: String, } async fn create_user(Json(user): Json) -> impl IntoApiResponse { Json(User { id: 1, name: user.name, email: user.email, }) } fn create_user_docs(op: aide::transform::TransformOperation) -> aide::transform::TransformOperation { op.description("Create a new user account") .response::<201, Json>() } async fn serve_openapi(Extension(api): Extension>) -> impl IntoApiResponse { Json(api) } fn api_docs(api: TransformOpenApi) -> TransformOpenApi { api.title("My API") .description("A REST API for user management") .tag(Tag { name: "users".into(), description: Some("User operations".into()), ..Default::default() }) } #[tokio::main] async fn main() { aide::generate::on_error(|error| println!("API doc error: {error}")); aide::generate::extract_schemas(true); let mut api = OpenApi::default(); let app = ApiRouter::new() .api_route("/users", post_with(create_user, create_user_docs)) .route("/openapi.json", get(serve_openapi)) .finish_api_with(&mut api, api_docs) .layer(Extension(Arc::new(api))); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); axum::serve(listener, app).await.unwrap(); } ``` -------------------------------- ### Embed Rust API Documentation UIs (Swagger, Redoc, Scalar) with aide Source: https://context7.com/tamasfe/aide/llms.txt This snippet shows how to integrate Swagger, Redoc, and Scalar documentation interfaces into an Axum application using the aide crate. It defines routes for serving the API specification and the respective UI interfaces. It depends on aide and axum crates. ```rust use aide::{ axum::{routing::get_with, ApiRouter}, openapi::OpenApi, redoc::Redoc, scalar::Scalar, swagger::Swagger, }; use axum::{Extension, Json}; use std::sync::Arc; async fn serve_api_spec(Extension(api): Extension>) -> Json { Json((*api).clone()) } fn docs_routes() -> ApiRouter { ApiRouter::new() .api_route_with( "/", get_with( Scalar::new("/docs/api.json") .with_title("My API Documentation") .axum_handler(), |op| op.description("Interactive API documentation (Scalar)").hidden(false), ), |p| p.tag("documentation"), ) .api_route_with( "/swagger", get_with( Swagger::new("/docs/api.json") .with_title("My API - Swagger UI") .axum_handler(), |op| op.description("Swagger UI documentation interface"), ), |p| p.tag("documentation"), ) .api_route_with( "/redoc", get_with( Redoc::new("/docs/api.json") .with_title("My API - Redoc") .axum_handler(), |op| op.description("Redoc documentation interface"), ), |p| p.tag("documentation"), ) .route("/api.json", axum::routing::get(serve_api_spec)) } fn main_router_with_docs() -> ApiRouter { let mut api = OpenApi::default(); let app = ApiRouter::new() .nest_api_service("/docs", docs_routes()); app.finish_api(&mut api) .layer(Extension(Arc::new(api))) } ``` -------------------------------- ### Documentation UI Generators Source: https://context7.com/tamasfe/aide/llms.txt This section explains how to embed interactive documentation interfaces like Scalar, Swagger UI, and Redoc into your application, providing access to the API specification. ```APIDOC ## Documentation Endpoints This router provides access to interactive API documentation interfaces. ### GET /docs/swagger #### Description Displays the API documentation using Swagger UI. #### Endpoint /docs/swagger ### GET /docs/redoc #### Description Displays the API documentation using Redoc. #### Endpoint /docs/redoc ### GET / #### Description Provides the interactive API documentation interface (Scalar). #### Endpoint / ### GET /api.json #### Description Serves the OpenAPI specification file in JSON format. #### Endpoint /api.json ``` -------------------------------- ### Generate Changelog with Git Cliff Source: https://github.com/tamasfe/aide/blob/master/CONTRIBUTING.md Command to generate a changelog for a specific crate using git-cliff. It requires a TOML configuration file and specifies the crate to include and the output file. ```shell git cliff --config "crates//cliff.toml" --include-path "crates//**/*" -l --prepend crates//CHANGELOG.md ``` -------------------------------- ### Custom Query Extractor with OpenAPI Documentation (Rust) Source: https://context7.com/tamasfe/aide/llms.txt Defines a custom query extractor `CustomQuery` that can be deserialized from request parameters. It implements `OperationInput` to automatically generate OpenAPI documentation for query parameters, including `search` (String) and an optional `limit` (u32). This allows for automatic API documentation generation for query-based inputs. ```rust use aide::{ generate::GenContext, operation::{OperationInput, OperationOutput}, openapi::{MediaType, Response, SchemaObject}, OperationIo, }; use axum::{ async_trait, extract::{FromRequest, Request}, response::{IntoResponse, Response as AxumResponse}, }; use schemars::{ schema_for, JsonSchema }; use serde::{ Deserialize, Serialize }; use std::collections::HashMap; // Custom extractor with documentation #[derive(Deserialize, JsonSchema)] struct CustomQuery { search: String, limit: Option, } impl OperationInput for CustomQuery { fn operation_input(ctx: &mut GenContext, operation: &mut aide::openapi::Operation) { let schema = ctx.schema.subschema_for::().into_object(); let params = aide::operation::parameters_from_schema( ctx, schema, aide::operation::ParamLocation::Query, ); aide::operation::add_parameters(ctx, operation, params); } } #[async_trait] impl FromRequest for CustomQuery where S: Send + Sync, { type Rejection = axum::http::StatusCode; async fn from_request(req: Request, state: &S) -> Result { let axum::extract::Query(query) = axum::extract::Query::::from_request(req, state) .await .map_err(|_| axum::http::StatusCode::BAD_REQUEST)?; Ok(query) } } ``` -------------------------------- ### Configure Rust API Security Schemes and Authentication with aide Source: https://context7.com/tamasfe/aide/llms.txt This snippet demonstrates how to define and apply security schemes (BearerAuth and ApiKey) to API routes using the aide crate. It includes a login endpoint and an authentication middleware to protect routes. It requires the aide, axum, schemars, and serde crates. ```rust use aide::{ axum::{routing::post_with, ApiRouter}, openapi::{OpenApi, SecurityScheme}, transform::TransformOpenApi, }; use axum::{extract::Request, middleware::Next, response::Response, Json}; use schemars::JsonSchema; use serde::Deserialize; #[derive(Deserialize, JsonSchema)] struct LoginRequest { username: String, password: String, } async fn login(Json(req): LoginRequest) -> aide::axum::IntoApiResponse { Json(serde_json::json!({ "token": "eyJ..." })).into_response() } async fn auth_middleware(req: Request, next: Next) -> Response { // Check Authorization header if let Some(auth) = req.headers().get("Authorization") { if auth.to_str().unwrap_or("").starts_with("Bearer ") { return next.run(req).await; } } axum::http::StatusCode::UNAUTHORIZED.into_response() } fn configure_api(api: TransformOpenApi) -> TransformOpenApi { api.title("Authenticated API") .security_scheme( "BearerAuth", SecurityScheme::Http { scheme: "bearer".into(), bearer_format: Some("JWT".into()), description: Some("JWT token authentication".into()), extensions: Default::default(), }, ) .security_scheme( "ApiKey", SecurityScheme::ApiKey { location: aide::openapi::ApiKeyLocation::Header, name: "X-API-Key".into(), description: Some("API key for service authentication".into()), extensions: Default::default(), }, ) .security_requirement("BearerAuth") } fn build_secured_app() -> ApiRouter { let mut api = OpenApi::default(); ApiRouter::new() .api_route( "/login", post_with(login, |op| { op.description("Authenticate and receive a JWT token") .tag("auth") .response::<200, Json>() }), ) .finish_api_with(&mut api, configure_api) .layer(axum::middleware::from_fn(auth_middleware)) } ``` -------------------------------- ### Security Schemes and Authentication Source: https://context7.com/tamasfe/aide/llms.txt This section details how to configure security schemes like Bearer token authentication and API keys, and apply them to routes using middleware. ```APIDOC ## POST /login ### Description Authenticate user credentials and receive a JWT token upon successful authentication. ### Method POST ### Endpoint /login ### Parameters #### Request Body - **username** (string) - Required - The username for login. - **password** (string) - Required - The password for login. ### Request Example ```json { "username": "user", "password": "password" } ``` ### Response #### Success Response (200) - **token** (string) - The JWT token for authenticated access. #### Response Example ```json { "token": "eyJ..." } ``` ## Security Schemes The API supports the following security schemes: ### BearerAuth - **Type**: HTTP - **Scheme**: bearer - **Bearer Format**: JWT - **Description**: JWT token authentication. ### ApiKey - **Type**: ApiKey - **Location**: Header - **Name**: X-API-Key - **Description**: API key for service authentication. ## Authentication Middleware Requests to secured endpoints are protected by an authentication middleware that checks for a valid `Authorization` header, specifically a `Bearer` token. ``` -------------------------------- ### Custom Query Extractor Documentation Source: https://context7.com/tamasfe/aide/llms.txt Defines a custom query extractor `CustomQuery` with parameters `search` and an optional `limit`. It implements `OperationInput` for OpenAPI documentation generation and `FromRequest` for use with Axum. ```APIDOC ## GET /search ### Description Handles search requests with custom query parameters. ### Method GET ### Endpoint /search ### Parameters #### Query Parameters - **search** (string) - Required - The search term. - **limit** (integer) - Optional - The maximum number of results to return. ### Request Example ```json { "search": "example", "limit": 10 } ``` ### Response #### Success Response (200) - **data** (array of strings) - The search results. - **meta** (object) - Metadata about the response, including count. #### Response Example ```json { "data": ["result1", "result2"], "meta": {"count": "2"} } ``` ``` -------------------------------- ### Rust: Create Reusable API Documentation Transforms with aide Source: https://context7.com/tamasfe/aide/llms.txt This snippet illustrates how to define reusable documentation transforms in Rust using the aide crate. It includes functions to add standard error responses (400, 401, 500), apply authentication requirements, and define parameters for paginated responses. These transforms can be applied to multiple API endpoints to ensure consistency. ```rust use aide::transform::{TransformOperation, TransformResponse}; use axum::Json; use schemars::JsonSchema; use serde::Serialize; use uuid::Uuid; #[derive(Serialize, JsonSchema)] struct ApiError { error: String, error_id: Uuid, timestamp: String, } // Reusable transform for adding standard error responses fn with_error_responses(op: TransformOperation) -> TransformOperation { op.response_with::<400, Json, _>(|res| { res.description("Invalid request parameters") .example(ApiError { error: "Invalid input".into(), error_id: Uuid::nil(), timestamp: "2024-01-01T00:00:00Z".into(), }) }) .response_with::<401, Json, _>(|res| { res.description("Authentication required") }) .response_with::<500, Json, _>(|res| { res.description("Internal server error") }) } // Reusable transform for authenticated endpoints fn authenticated(op: TransformOperation) -> TransformOperation { op.security_requirement("BearerAuth") .with(with_error_responses) } // Reusable transform for paginated responses fn paginated(op: TransformOperation) -> TransformOperation { op.parameter_untyped("page", |param| { param.description("Page number (1-indexed)") }) .parameter_untyped("limit", |param| { param.description("Number of items per page") }) } #[derive(Serialize, JsonSchema)] struct UserList { users: Vec, total: u32, } async fn list_users_handler() -> Json { Json(UserList { users: vec!["alice".into(), "bob".into()], total: 2, }) } fn create_routes() -> aide::axum::ApiRouter { use aide::axum::routing::get_with; aide::axum::ApiRouter::new().api_route( "/users", get_with(list_users_handler, |op| { op.description("List all users with pagination") .tag("users") .response::<200, Json>() .with(authenticated) .with(paginated) }), ) } ``` -------------------------------- ### Custom Response Documentation Source: https://context7.com/tamasfe/aide/llms.txt Defines a generic custom response structure `CustomResponse` which includes data and metadata. It implements `OperationOutput` for OpenAPI documentation and `IntoResponse` for use with Axum. ```APIDOC ## Custom Response Structure ### Description Represents a standardized response format that includes a data payload and associated metadata. ### Method N/A (This is a response structure definition) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response #### Success Response (200) - **data** (type T) - The primary payload of the response, can be any serializable type. - **meta** (object) - A collection of key-value pairs providing additional information about the response. #### Response Example ```json { "data": [], "meta": { "key": "value" } } ``` ``` -------------------------------- ### Users API Source: https://context7.com/tamasfe/aide/llms.txt Endpoint for listing users with pagination and authentication. ```APIDOC ## GET /users ### Description List all users with pagination. ### Method GET ### Endpoint /users ### Parameters #### Query Parameters - **page** (untyped) - Optional - Page number (1-indexed) - **limit** (untyped) - Optional - Number of items per page #### Request Body None ### Request Example None ### Response #### Success Response (200) - **users** (array) - Description - **total** (u32) - Description #### Response Example ```json { "users": [ "alice", "bob" ], "total": 2 } ``` #### Error Response (400) - **error** (string) - Description - **error_id** (uuid) - Description - **timestamp** (string) - Description #### Error Response (401) - **error** (string) - Description - **error_id** (uuid) - Description - **timestamp** (string) - Description #### Error Response (500) - **error** (string) - Description - **error_id** (uuid) - Description - **timestamp** (string) - Description ``` -------------------------------- ### Rust CRUD API Implementation with Aide and Axum Source: https://context7.com/tamasfe/aide/llms.txt This snippet showcases a full CRUD API for managing todo items. It includes state management for todos, request/response handling for creation, listing, retrieval, updates, and deletions. Dependencies include Aide, Axum, schemars, serde, tokio, and uuid. ```rust use aide::{ axum::{ routing::{delete_with, get_with, post_with, put_with}, ApiRouter, IntoApiResponse, }, openapi::Tag, transform::TransformOpenApi, }; use axum::{ extract::{Path, State}, http::StatusCode, Json, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::sync::Arc; use tokio::sync::RwLock; use uuid::Uuid; #[derive(Clone)] struct AppState { todos: Arc>>, } #[derive(Clone, Serialize, Deserialize, JsonSchema)] struct Todo { id: Uuid, title: String, completed: bool, } #[derive(Deserialize, JsonSchema)] struct CreateTodo { title: String, } #[derive(Deserialize, JsonSchema)] struct UpdateTodo { title: Option, completed: Option, } async fn create_todo( State(state): State, Json(req): Json, ) -> impl IntoApiResponse { let todo = Todo { id: Uuid::new_v4(), title: req.title, completed: false, }; state.todos.write().await.push(todo.clone()); (StatusCode::CREATED, Json(todo)) } async fn list_todos(State(state): State) -> impl IntoApiResponse { let todos = state.todos.read().await; Json(todos.clone()) } async fn get_todo(State(state): State, Path(id): Path) -> impl IntoApiResponse { let todos = state.todos.read().await; match todos.iter().find(|t| t.id == id) { Some(todo) => Json(todo.clone()).into_response(), None => StatusCode::NOT_FOUND.into_response(), } } async fn update_todo( State(state): State, Path(id): Path, Json(req): Json, ) -> impl IntoApiResponse { let mut todos = state.todos.write().await; match todos.iter_mut().find(|t| t.id == id) { Some(todo) => { if let Some(title) = req.title { todo.title = title; } if let Some(completed) = req.completed { todo.completed = completed; } Json(todo.clone()).into_response() } None => StatusCode::NOT_FOUND.into_response(), } } async fn delete_todo( State(state): State, Path(id): Path, ) -> impl IntoApiResponse { let mut todos = state.todos.write().await; if let Some(pos) = todos.iter().position(|t| t.id == id) { todos.remove(pos); StatusCode::NO_CONTENT } else { StatusCode::NOT_FOUND } } fn todo_routes(state: AppState) -> ApiRouter { ApiRouter::new() .api_route( "/", post_with(create_todo, |op| { op.description("Create a new todo item") .response::<201, Json>() }) .get_with(list_todos, |op| { op.description("List all todo items") .response::<200, Json>>() }), ) .api_route( "/{id}", get_with(get_todo, |op| { op.description("Get a single todo by ID") .response::<200, Json>() .response_with::<404, (), _>(|r| r.description("Todo not found")) }) .put_with(update_todo, |op| { op.description("Update an existing todo") .response::<200, Json>() .response_with::<404, (), _>(|r| r.description("Todo not found")) }) .delete_with(delete_todo, |op| { op.description("Delete a todo item") .response::<204, ()>() .response_with::<404, (), _>(|r| r.description("Todo not found")) }), ) .with_state(state) } fn configure_api(api: TransformOpenApi) -> TransformOpenApi { api.title("Todo API") .description("A simple todo list API") .tag(Tag { name: "todos".into(), description: Some("Todo item management".into()), ..Default::default() }) } #[tokio::main] async fn main() { let state = AppState { todos: Arc::new(RwLock::new(vec![])), }; let mut api = aide::openapi::OpenApi::default(); let app = ApiRouter::new() .nest_api_service("/todos", todo_routes(state.clone())) .finish_api_with(&mut api, configure_api) .layer(axum::Extension(Arc::new(api))) .with_state(state); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000") .await .unwrap(); axum::serve(listener, app).await.unwrap(); } ``` -------------------------------- ### Todo Management API Source: https://context7.com/tamasfe/aide/llms.txt This section details the API endpoints for managing todo items. It covers creating, listing, retrieving, updating, and deleting todos. ```APIDOC ## POST /todos ### Description Create a new todo item. ### Method POST ### Endpoint /todos ### Parameters #### Query Parameters None #### Request Body - **title** (string) - Required - The title of the todo item. ### Request Example ```json { "title": "Buy groceries" } ``` ### Response #### Success Response (201) - **id** (string) - The unique identifier for the todo item. - **title** (string) - The title of the todo item. - **completed** (boolean) - Indicates if the todo item is completed. #### Response Example ```json { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "title": "Buy groceries", "completed": false } ``` ## GET /todos ### Description List all todo items. ### Method GET ### Endpoint /todos ### Parameters #### Query Parameters None #### Request Body None ### Response #### Success Response (200) - **Array of Todo objects** (object array) - A list of all todo items. - **id** (string) - The unique identifier for the todo item. - **title** (string) - The title of the todo item. - **completed** (boolean) - Indicates if the todo item is completed. #### Response Example ```json [ { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "title": "Buy groceries", "completed": false }, { "id": "b2c3d4e5-f6a7-8901-2345-67890abcdef0", "title": "Walk the dog", "completed": true } ] ``` ## GET /todos/{id} ### Description Get a single todo by its unique identifier. ### Method GET ### Endpoint /todos/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the todo item. #### Query Parameters None #### Request Body None ### Response #### Success Response (200) - **id** (string) - The unique identifier for the todo item. - **title** (string) - The title of the todo item. - **completed** (boolean) - Indicates if the todo item is completed. #### Response Example ```json { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "title": "Buy groceries", "completed": false } ``` #### Error Response (404) - **Description**: Todo not found. ## PUT /todos/{id} ### Description Update an existing todo item. ### Method PUT ### Endpoint /todos/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the todo item to update. #### Query Parameters None #### Request Body - **title** (string) - Optional - The new title for the todo item. - **completed** (boolean) - Optional - The new completion status for the todo item. ### Request Example ```json { "completed": true } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier for the todo item. - **title** (string) - The updated title of the todo item. - **completed** (boolean) - The updated completion status of the todo item. #### Response Example ```json { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "title": "Buy groceries", "completed": true } ``` #### Error Response (404) - **Description**: Todo not found. ## DELETE /todos/{id} ### Description Delete a todo item by its unique identifier. ### Method DELETE ### Endpoint /todos/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the todo item to delete. #### Query Parameters None #### Request Body None ### Response #### Success Response (204) - **Description**: No content, indicating successful deletion. #### Error Response (404) - **Description**: Todo not found. ``` -------------------------------- ### Rust: Configure Axum Error Handling and Response Inference with aide Source: https://context7.com/tamasfe/aide/llms.txt This Rust code configures aide for Axum to automatically infer responses and handle errors. It defines custom success and error response structures, implements necessary traits for aide integration, and sets up routes with error handling logic. Dependencies include `aide`, `axum`, and `schemars`. ```rust use aide::{ axum::{routing::get_with, ApiRouter, IntoApiResponse}, generate, }; use axum::{extract::Path, http::StatusCode, response::IntoResponse, Json}; use schemars::JsonSchema; use serde::Serialize; #[derive(Serialize, JsonSchema)] struct ErrorResponse { error: String, code: u16, } #[derive(Serialize, JsonSchema)] struct SuccessData { id: u64, value: String, } type ApiResult = Result, ApiError>; struct ApiError { status: StatusCode, message: String, } impl IntoResponse for ApiError { fn into_response(self) -> axum::response::Response { ( self.status, Json(ErrorResponse { error: self.message, code: self.status.as_u16(), }), ) .into_response() } } impl aide::OperationOutput for ApiError { type Inner = ErrorResponse; fn operation_response( ctx: &mut aide::generate::GenContext, _operation: &mut aide::openapi::Operation, ) -> Option { Some(aide::openapi::Response { description: "Error response".into(), content: [( "application/json".into(), aide::openapi::MediaType { schema: Some(aide::openapi::SchemaObject { json_schema: ctx.schema.subschema_for::(), example: None, external_docs: None, }), ..Default::default() }, )] .into(), ..Default::default() }) } fn inferred_responses( ctx: &mut aide::generate::GenContext, operation: &mut aide::openapi::Operation, ) -> Vec<(Option, aide::openapi::Response)> { vec![(None, Self::operation_response(ctx, operation).unwrap())] } } async fn get_item(Path(id): Path) -> ApiResult { if id == 0 { return Err(ApiError { status: StatusCode::BAD_REQUEST, message: "ID cannot be zero".into(), }); } Ok(Json(SuccessData { id, value: format!("Item {}", id), })) } fn setup_error_handling() -> ApiRouter { // Register error handler for documentation generation generate::on_error(|error| { eprintln!("Documentation generation error: {}", error); }); // Enable response inference generate::infer_responses(true); // Configure empty response status (default for unit returns) generate::inferred_empty_response_status(204); ApiRouter::new().api_route( "/items/{id}", get_with(get_item, |op| { op.description("Get item by ID, returns error on invalid ID") .tag("items") }), ) } ``` -------------------------------- ### Custom Response with OpenAPI Documentation (Rust) Source: https://context7.com/tamasfe/aide/llms.txt Defines a generic custom response `CustomResponse` that includes data and metadata. It implements `OperationOutput` to automatically generate OpenAPI documentation for responses, specifying the content type as `application/json` and including a schema for the response body. This facilitates automatic API documentation for structured responses. ```rust use aide::{ generate::GenContext, operation::{OperationInput, OperationOutput}, openapi::{MediaType, Response, SchemaObject}, OperationIo, }; use axum::{ async_trait, extract::{FromRequest, Request}, response::{IntoResponse, Response as AxumResponse}, }; use schemars::{ schema_for, JsonSchema }; use serde::{ Deserialize, Serialize }; use std::collections::HashMap; // Custom response with documentation #[derive(Serialize, JsonSchema)] struct CustomResponse { data: T, meta: HashMap, } impl OperationOutput for CustomResponse where T: JsonSchema + Serialize, { type Inner = Self; fn operation_response( ctx: &mut GenContext, _operation: &mut aide::openapi::Operation, ) -> Option { let schema = ctx.schema.subschema_for::(); Some(Response { description: "Successful response with metadata".into(), content: [( "application/json".into(), MediaType { schema: Some(SchemaObject { json_schema: schema, example: None, external_docs: None, }), ..Default::default() }, )] .into(), ..Default::default() }) } fn inferred_responses( ctx: &mut GenContext, operation: &mut aide::openapi::Operation, ) -> Vec<(Option, Response)> { vec![(Some(200), Self::operation_response(ctx, operation).unwrap())] } } impl IntoResponse for CustomResponse { fn into_response(self) -> AxumResponse { axum::Json(self).into_response() } } ``` -------------------------------- ### Posts API Source: https://context7.com/tamasfe/aide/llms.txt Endpoints for managing posts, including listing all posts and retrieving a single post by its ID. ```APIDOC ## GET /posts ### Description List all posts. ### Method GET ### Endpoint /posts ### Parameters #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **(object)** - Description #### Response Example ```json [ { "id": 1, "title": "First Post", "content": "Content here" } ] ``` ``` ```APIDOC ## GET /posts/{id} ### Description Get a single post by ID. ### Method GET ### Endpoint /posts/{id} ### Parameters #### Path Parameters - **id** (u64) - Required - The ID of the post to retrieve. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **(object)** - Description #### Response Example ```json { "id": 1, "title": "First Post", "content": "Content here" } ``` #### Error Response (404) - **None** - Post not found ``` -------------------------------- ### Error Handling and Response Inference API Source: https://context7.com/tamasfe/aide/llms.txt This section details the implementation of custom error handling and automatic response inference within the aide framework, using Axum as the web framework. ```APIDOC ## GET /items/{id} ### Description Get item by ID. Returns a success response with item data or an error response if the provided ID is invalid (e.g., zero). ### Method GET ### Endpoint /items/{id} ### Parameters #### Path Parameters - **id** (u64) - Required - The unique identifier for the item. ### Request Body This endpoint does not have a request body. ### Request Example ```json { "example": "No request body for GET request" } ``` ### Response #### Success Response (200) - **id** (u64) - The ID of the item. - **value** (string) - The value associated with the item. #### Error Response (400) - **error** (string) - A message describing the error. - **code** (u16) - The HTTP status code. #### Response Example (Success) ```json { "id": 1, "value": "Item 1" } ``` #### Response Example (Error) ```json { "error": "ID cannot be zero", "code": 400 } ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.