#アップロードファイルサイズ制限 ミドルウェア
リクエストのアップロードファイルサイズ制限を提供するミドルウェアです。
#適用シナリオ
Size Limiter は主に以下のシナリオで使用されます:
- ユーザーが過大なファイルをアップロードしてサーバーリソースを占有するのを防止
- 悪意のある攻撃者が大量データをアップロードしてサーバーメモリオーバーフローを引き起こすのを回避
- 異なるAPIエンドポイントに対して異なるリクエストサイズ制限ポリシーを設定
- サーバーのリクエスト処理効率と安定性の向上
サンプルコード
main.rs
Cargo.toml
use std::fs::create_dir_all;
use std::path::Path;
use salvo::prelude::*;
#[handler]
async fn index(res: &mut Response) {
res.render(Text::Html(INDEX_HTML));
}
#[handler]
async fn upload(req: &mut Request, res: &mut Response) {
let file = req.file("file").await;
if let Some(file) = file {
let dest = format!("temp/{}", file.name().unwrap_or("file"));
tracing::debug!(dest, "upload file");
if let Err(e) = std::fs::copy(file.path(), Path::new(&dest)) {
res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
res.render(Text::Plain(format!("file not found in request: {e}")));
} else {
res.render(Text::Plain(format!("File uploaded to {dest}")));
}
} else {
res.status_code(StatusCode::BAD_REQUEST);
res.render(Text::Plain("file not found in request"));
}
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().init();
create_dir_all("temp").unwrap();
let router = Router::new()
.get(index)
.push(
Router::new()
.hoop(max_size(1024 * 1024 * 10))
.path("limited")
.post(upload),
)
.push(Router::with_path("unlimit").post(upload));
let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
Server::new(acceptor).serve(router).await;
}
static INDEX_HTML: &str = r#"<!DOCTYPE html>
<html>
<head>
<title>Upload file</title>
</head>
<body>
<h1>Upload file</h1>
<form action="/unlimit" method="post" enctype="multipart/form-data">
<h3>Unlimit</h3>
<input type="file" name="file" />
<input type="submit" value="upload" />
</form>
<form action="/limited" method="post" enctype="multipart/form-data">
<h3>Limited 10MiB</h3>
<input type="file" name="file" />
<input type="submit" value="upload" />
</form>
</body>
</html>
"#;
[package]
name = "example-size-limiter"
version.workspace = true
edition.workspace = true
publish.workspace = true
rust-version.workspace = true
[dependencies]
salvo = { workspace = true, features = ["size-limiter"] }
tokio = { workspace = true, features = ["macros"] }
tracing.workspace = true
tracing-subscriber.workspace = true