本記事では、cssや画像等staticなファイルを配信するための方法を記載します。
axumのExampleではRouterに関数を登録しルーティングする方法を記載していますが、cssや画像を返すにはどうすればいいのか?という内容です。
- 環境
cargo v1.63.0
axum v0.5.1
tower-http v0.3.4
- 構成
/
- Cargo.toml
- resource/
- icon.png
- src/
- bin/
- route.rs
実装
tower_http::services::ServeDir
という、特定ディレクトリおよびその子ディレクトリにあるファイルを提供できるサービスクラスを利用します。
axumはtowerを利用しており Router::route へ任意のServiceクラスを設定できるので、そこにServeDirを渡してやります。
1. 依存関係を追加
cargo add tower-http -F 'fs'
Cargo.toml に依存関係が追記され、ServeDirを利用できるようになります。
2. Routerにルーティング追加
RouterにServeDirを設定します。
use axum::{
Router,
routing::get_service,
http::StatusCode,
};
use std::io;
use tower_http::services::ServeDir;
// axum::routing::get_service でgetリクエストにServiceを対応させる
// その他のHTTPリクエストに対応させたい場合はpost_service等へ適宜変更
let serve_resource_dir_service = get_service(ServeDir::new("resource"))
.handle_error(|error: io::Error| async move {
(
StatusCode::NOT_FOUND,
format!("file not found: {}", error),
)
});
// Router::nest で、 /resource 以下へのアクセスを作成したServiceへ委託するようルーティング設定
let app = Router::new()
.nest("/resource", serve_resource_dir_service);
注意点として、Router::route
ではなく Router::nest
を使う必要があります。
routeの場合はルーティング設定したパスが完全一致したリクエストのみが処理されますが、nestの場合パスが前方一致した時点で以降の処理がネストした処理に回されます。
今回は resource/ 以下に来たアクセスはファイル名含め全てServeDirに処理して欲しいので、Router::nest
を使います。
3. アクセス確認
cargo run
でサーバ起動後、ブラウザから localhost:3000/resource/icon.png にアクセスします。
配置した画像が表示されていれば成功です。
おわりに
以上がaxumでstaticなファイルへのルーティングを行う方法となります。tower_htmlにあるその他のServiceも同様にしてルーティング設定できそうな雰囲気です。
大規模なアプリ開発ではフロントエンドはReact等に任せてしまった方がいいかもしれませんが、
minijinja辺りと組み合わせることで小規模アプリのレイアウトを手軽に作れそうです。
参考
-
公式ドキュメント Struct axum::routing::Router
-
https://docs.rs/axum/latest/axum/routing/struct.Router.html#nesting-services
-
This can for example be used with tower_http::services::ServeDir to serve static files from a directory:
-
よくよく調べたら公式に書いてあったというお話
-
-
-
Rustの新しいWebフレームワークaxumのtokio、tower、hyperとの関係を整理する
-
Serve static content with axum
-
https://bloerg.net/posts/serve-static-content-with-axum/
- 恐らくアンチパターン 自前でURIをパースしてファイル読み込みしMIMEtypeを付与して返す、という方法
- ServeDir を使えばパスのバリデーションやパーミッションも適切に処理してくれるため、公式が用意した方法を使う方が良いと思われます
-
https://bloerg.net/posts/serve-static-content-with-axum/