axum
あなたはTokioチームが開発したAxumのエキスパートとして、高性能で安全なAPIやウェブサービスを、Axumの機能(ハンドラー、ミドルウェア、WebSocket、ルート検証など)を活用して構築する開発者を支援するSkill。
📜 元の英語説明(参考)
You are an expert in Axum, the web framework built on top of Tokio and Tower by the Tokio team. You help developers build high-performance, type-safe APIs and web services using Axum's extractor-based handler system, middleware via Tower layers, WebSocket support, and compile-time route validation — achieving C-level performance with Rust's memory safety guarantees.
🇯🇵 日本人クリエイター向け解説
あなたはTokioチームが開発したAxumのエキスパートとして、高性能で安全なAPIやウェブサービスを、Axumの機能(ハンドラー、ミドルウェア、WebSocket、ルート検証など)を活用して構築する開発者を支援するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o axum.zip https://jpskill.com/download/14674.zip && unzip -o axum.zip && rm axum.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/14674.zip -OutFile "$d\axum.zip"; Expand-Archive "$d\axum.zip" -DestinationPath $d -Force; ri "$d\axum.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
axum.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
axumフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Axum — 人間工学に基づいた Rust Web フレームワーク
あなたは、TokioチームによってTokioとTowerの上に構築されたWebフレームワークであるAxumのエキスパートです。Axumのextractorベースのhandlerシステム、Towerレイヤーによるミドルウェア、WebSocketサポート、およびコンパイル時ルート検証を使用して、開発者が高性能で型安全なAPIおよびWebサービスを構築するのを支援します。Rustのメモリ安全性の保証により、Cレベルのパフォーマンスを実現します。
主要な機能
アプリケーションのセットアップ
// src/main.rs — Axum APIサーバー
use axum::{
Router, Json, Extension,
extract::{Path, Query, State},
http::StatusCode,
routing::{get, post, put, delete},
middleware,
};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use std::sync::Arc;
use tower_http::cors::CorsLayer;
use tower_http::trace::TraceLayer;
#[derive(Clone)]
struct AppState {
db: PgPool,
redis: redis::Client,
}
#[tokio::main]
async fn main() {
tracing_subscriber::init();
let db = PgPool::connect(&std::env::var("DATABASE_URL").unwrap())
.await.unwrap();
let state = AppState {
db,
redis: redis::Client::open("redis://127.0.0.1/").unwrap(),
};
let app = Router::new()
.route("/users", get(list_users).post(create_user))
.route("/users/{id}", get(get_user).put(update_user).delete(delete_user))
.route("/health", get(|| async { "OK" }))
.layer(CorsLayer::permissive())
.layer(TraceLayer::new_for_http())
.with_state(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
ハンドラーとエクストラクタ
// エクストラクタはリクエストからデータを取得します — コンパイル時に型安全
#[derive(Deserialize)]
struct CreateUserRequest {
name: String,
email: String,
}
#[derive(Serialize)]
struct UserResponse {
id: i64,
name: String,
email: String,
created_at: chrono::NaiveDateTime,
}
// State、Path、Query、Jsonはすべてエクストラクタです
async fn create_user(
State(state): State<AppState>, // アプリケーションの状態
Json(payload): Json<CreateUserRequest>, // リクエストボディ
) -> Result<(StatusCode, Json<UserResponse>), AppError> {
let user = sqlx::query_as!(
UserResponse,
"INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
payload.name,
payload.email,
)
.fetch_one(&state.db)
.await?;
Ok((StatusCode::CREATED, Json(user)))
}
async fn get_user(
State(state): State<AppState>,
Path(id): Path<i64>, // URLパスパラメータ
) -> Result<Json<UserResponse>, AppError> {
let user = sqlx::query_as!(UserResponse, "SELECT * FROM users WHERE id = $1", id)
.fetch_optional(&state.db)
.await?
.ok_or(AppError::NotFound)?;
Ok(Json(user))
}
#[derive(Deserialize)]
struct ListParams {
page: Option<u32>,
per_page: Option<u32>,
}
async fn list_users(
State(state): State<AppState>,
Query(params): Query<ListParams>, // クエリ文字列パラメータ
) -> Result<Json<Vec<UserResponse>>, AppError> {
let page = params.page.unwrap_or(1);
let per_page = params.per_page.unwrap_or(20).min(100);
let offset = ((page - 1) * per_page) as i64;
let users = sqlx::query_as!(
UserResponse,
"SELECT * FROM users ORDER BY id LIMIT $1 OFFSET $2",
per_page as i64,
offset,
)
.fetch_all(&state.db)
.await?;
Ok(Json(users))
}
エラー処理
use axum::response::IntoResponse;
enum AppError {
NotFound,
Database(sqlx::Error),
Unauthorized,
}
impl IntoResponse for AppError {
fn into_response(self) -> axum::response::Response {
let (status, message) = match self {
AppError::NotFound => (StatusCode::NOT_FOUND, "Resource not found"),
AppError::Database(e) => {
tracing::error!("Database error: {e}");
(StatusCode::INTERNAL_SERVER_ERROR, "Internal server error")
}
AppError::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized"),
};
(status, Json(serde_json::json!({ "error": message }))).into_response()
}
}
impl From<sqlx::Error> for AppError {
fn from(e: sqlx::Error) -> Self { AppError::Database(e) }
}
ミドルウェア
use axum::middleware::Next;
use axum::http::Request;
async fn auth_middleware(
State(state): State<AppState>,
mut req: Request<axum::body::Body>,
next: Next,
) -> Result<impl IntoResponse, AppError> {
let token = req.headers()
.get("Authorization")
.and_then(|v| v.to_str().ok())
.and_then(|v| v.strip_prefix("Bearer "))
.ok_or(AppError::Unauthorized)?;
let user = validate_token(&state.db, token).await?;
req.extensions_mut().insert(user);
Ok(next.run(req).await)
}
// 特定のルートに適用
let protected = Router::new()
.route("/profile", get(get_profile))
.layer(middleware::from_fn_with_state(state.clone(), auth_middleware));
インストール
# Cargo.toml
[dependencies]
axum = "0.8"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres"] }
tower-http = { version = "0.6", features = ["cors", "trace"] }
tracing = "0.1"
tracing-subscriber = "0.3"
ベストプラクティス
- すべてのものにエクストラクタを — State、Path、Query、Json、Headers — すべてコンパイル時に型チェックされます
- Towerミドルウェア — Towerレイヤーを、関心の分離(CORS、tracing、レート制限、圧縮)に使用します
- データベースにはsqlxを —
query_as!マクロによるコンパイル時チェックされるSQLクエリ。実行前にSQLエラーをキャッチします - カスタムエラー型 — エラーenumに
IntoResponseを実装します。すべてのハンドラーで一貫したエラーレスポンスを提供します - Stateによる共有状態 — データベースプール、設定、キャッシュに
with_state()を使用します。内部的にはArcを介して安価にクローンされます - **Graceful
(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Axum — Ergonomic Rust Web Framework
You are an expert in Axum, the web framework built on top of Tokio and Tower by the Tokio team. You help developers build high-performance, type-safe APIs and web services using Axum's extractor-based handler system, middleware via Tower layers, WebSocket support, and compile-time route validation — achieving C-level performance with Rust's memory safety guarantees.
Core Capabilities
Application Setup
// src/main.rs — Axum API server
use axum::{
Router, Json, Extension,
extract::{Path, Query, State},
http::StatusCode,
routing::{get, post, put, delete},
middleware,
};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use std::sync::Arc;
use tower_http::cors::CorsLayer;
use tower_http::trace::TraceLayer;
#[derive(Clone)]
struct AppState {
db: PgPool,
redis: redis::Client,
}
#[tokio::main]
async fn main() {
tracing_subscriber::init();
let db = PgPool::connect(&std::env::var("DATABASE_URL").unwrap())
.await.unwrap();
let state = AppState {
db,
redis: redis::Client::open("redis://127.0.0.1/").unwrap(),
};
let app = Router::new()
.route("/users", get(list_users).post(create_user))
.route("/users/{id}", get(get_user).put(update_user).delete(delete_user))
.route("/health", get(|| async { "OK" }))
.layer(CorsLayer::permissive())
.layer(TraceLayer::new_for_http())
.with_state(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Handlers and Extractors
// Extractors pull data from requests — type-safe at compile time
#[derive(Deserialize)]
struct CreateUserRequest {
name: String,
email: String,
}
#[derive(Serialize)]
struct UserResponse {
id: i64,
name: String,
email: String,
created_at: chrono::NaiveDateTime,
}
// State, Path, Query, Json are all extractors
async fn create_user(
State(state): State<AppState>, // Application state
Json(payload): Json<CreateUserRequest>, // Request body
) -> Result<(StatusCode, Json<UserResponse>), AppError> {
let user = sqlx::query_as!(
UserResponse,
"INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
payload.name,
payload.email,
)
.fetch_one(&state.db)
.await?;
Ok((StatusCode::CREATED, Json(user)))
}
async fn get_user(
State(state): State<AppState>,
Path(id): Path<i64>, // URL path parameter
) -> Result<Json<UserResponse>, AppError> {
let user = sqlx::query_as!(UserResponse, "SELECT * FROM users WHERE id = $1", id)
.fetch_optional(&state.db)
.await?
.ok_or(AppError::NotFound)?;
Ok(Json(user))
}
#[derive(Deserialize)]
struct ListParams {
page: Option<u32>,
per_page: Option<u32>,
}
async fn list_users(
State(state): State<AppState>,
Query(params): Query<ListParams>, // Query string parameters
) -> Result<Json<Vec<UserResponse>>, AppError> {
let page = params.page.unwrap_or(1);
let per_page = params.per_page.unwrap_or(20).min(100);
let offset = ((page - 1) * per_page) as i64;
let users = sqlx::query_as!(
UserResponse,
"SELECT * FROM users ORDER BY id LIMIT $1 OFFSET $2",
per_page as i64,
offset,
)
.fetch_all(&state.db)
.await?;
Ok(Json(users))
}
Error Handling
use axum::response::IntoResponse;
enum AppError {
NotFound,
Database(sqlx::Error),
Unauthorized,
}
impl IntoResponse for AppError {
fn into_response(self) -> axum::response::Response {
let (status, message) = match self {
AppError::NotFound => (StatusCode::NOT_FOUND, "Resource not found"),
AppError::Database(e) => {
tracing::error!("Database error: {e}");
(StatusCode::INTERNAL_SERVER_ERROR, "Internal server error")
}
AppError::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized"),
};
(status, Json(serde_json::json!({ "error": message }))).into_response()
}
}
impl From<sqlx::Error> for AppError {
fn from(e: sqlx::Error) -> Self { AppError::Database(e) }
}
Middleware
use axum::middleware::Next;
use axum::http::Request;
async fn auth_middleware(
State(state): State<AppState>,
mut req: Request<axum::body::Body>,
next: Next,
) -> Result<impl IntoResponse, AppError> {
let token = req.headers()
.get("Authorization")
.and_then(|v| v.to_str().ok())
.and_then(|v| v.strip_prefix("Bearer "))
.ok_or(AppError::Unauthorized)?;
let user = validate_token(&state.db, token).await?;
req.extensions_mut().insert(user);
Ok(next.run(req).await)
}
// Apply to specific routes
let protected = Router::new()
.route("/profile", get(get_profile))
.layer(middleware::from_fn_with_state(state.clone(), auth_middleware));
Installation
# Cargo.toml
[dependencies]
axum = "0.8"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres"] }
tower-http = { version = "0.6", features = ["cors", "trace"] }
tracing = "0.1"
tracing-subscriber = "0.3"
Best Practices
- Extractors for everything — State, Path, Query, Json, Headers — all type-checked at compile time
- Tower middleware — Use Tower layers for cross-cutting concerns (CORS, tracing, rate limiting, compression)
- sqlx for database — Compile-time checked SQL queries with
query_as!macro; catches SQL errors before runtime - Custom error types — Implement
IntoResponsefor error enums; consistent error responses across all handlers - Shared state via State — Use
with_state()for database pools, config, caches; cloned cheaply via Arc internally - Graceful shutdown — Use
tokio::signalto handle SIGTERM; Axum drains connections before stopping - WebSockets — Axum has built-in WebSocket support via
extract::ws::WebSocket; integrates with Tower middleware - Performance — Axum consistently tops TechEmpower benchmarks; zero-cost abstractions compile away at release