axum-guide

Axum v0.8.x Development Guide

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "axum-guide" with this command: npx skills add daiki48/dotfiles/daiki48-dotfiles-axum-guide

Axum v0.8.x Development Guide

Handlers

use axum::{extract::{Path, Query, State, Json}, response::IntoResponse, http::StatusCode};

async fn get_user( State(pool): State<PgPool>, Path(id): Path<i32>, ) -> Result<Json<User>, AppError> { let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id) .fetch_one(&pool).await?; Ok(Json(user)) }

async fn create_user( State(pool): State<PgPool>, claims: Claims, // Custom extractor Json(payload): Json<CreateUserRequest>, ) -> Result<(StatusCode, Json<User>), AppError> { // ... Ok((StatusCode::CREATED, Json(user))) }

Routing

fn app() -> Router<AppState> { Router::new() .route("/", get(root)) .route("/users", get(list_users).post(create_user)) .route("/users/:id", get(get_user).put(update_user).delete(delete_user)) .nest("/api", api_routes()) .layer(middleware_stack()) .with_state(state) }

Error Handling

pub struct AppError { pub code: StatusCode, pub message: String, }

impl IntoResponse for AppError { fn into_response(self) -> Response { (self.code, Json(json!({"error": self.message}))).into_response() } }

impl From<sqlx::Error> for AppError { fn from(err: sqlx::Error) -> Self { match err { sqlx::Error::RowNotFound => AppError { code: StatusCode::NOT_FOUND, message: "Resource not found".into(), }, _ => AppError { code: StatusCode::INTERNAL_SERVER_ERROR, message: "Database error".into(), }, } } }

Middleware

async fn logging_middleware(req: Request, next: Next) -> Response { let method = req.method().clone(); let uri = req.uri().clone(); let response = next.run(req).await; tracing::info!("{} {} -> {}", method, uri, response.status()); response }

let app = Router::new() .route("/", get(handler)) .layer(middleware::from_fn(logging_middleware));

Custom Extractor

pub struct Claims { pub user_id: i32, pub role: String }

#[async_trait] impl<S: Send + Sync> FromRequestParts<S> for Claims { type Rejection = AppError;

async fn from_request_parts(parts: &#x26;mut Parts, _state: &#x26;S) -> Result&#x3C;Self, Self::Rejection> {
    let token = parts.headers.get("cookie")
        .and_then(|v| v.to_str().ok())
        .and_then(extract_token)
        .ok_or(AppError::unauthorized("No token"))?;
    validate_jwt(&#x26;token)
}

}

Auth Middleware

async fn auth_middleware(claims: Claims, req: Request, next: Next) -> Response { next.run(req).await }

let protected = Router::new() .route("/profile", get(profile)) .layer(middleware::from_fn(auth_middleware));

CORS

use tower_http::cors::{CorsLayer, Any};

let cors = CorsLayer::new() .allow_origin(Any) .allow_methods(Any) .allow_headers(Any) .allow_credentials(true);

Response Headers & Cookies

async fn login() -> impl IntoResponse { let cookie = format!( "token={}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age={}", token, max_age ); ([(header::SET_COOKIE, cookie)], Json(response)) }

File Upload

async fn upload(mut multipart: Multipart) -> Result<(), AppError> { while let Some(field) = multipart.next_field().await? { let name = field.name().unwrap_or_default().to_string(); let data = field.bytes().await?; // Process file } Ok(()) }

Notes

  • Extractor order: Put State last (others may consume body)

  • Consistent error type: Use single AppError across app

  • Middleware order: Executes outer→inner (reverse of layer order)

  • State type: Must implement Clone (usually wrap in Arc )

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

leptos-guide

No summary provided by upstream source.

Repository SourceNeeds Review
General

sqlx-postgres

No summary provided by upstream source.

Repository SourceNeeds Review
General

dioxus-guide

No summary provided by upstream source.

Repository SourceNeeds Review
General

rust-fullstack

No summary provided by upstream source.

Repository SourceNeeds Review