feat: Configure a 10GB body limit for uploads and enhance attachment processing with a 100MB image size cap and improved error handling.
This commit is contained in:
@@ -35,7 +35,7 @@ pub struct AttachmentsTemplate<'a> {
|
|||||||
pub fn router() -> Router<Arc<AppState>> {
|
pub fn router() -> Router<Arc<AppState>> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", get(list_attachments))
|
.route("/", get(list_attachments))
|
||||||
.route("/upload", post(upload_attachment))
|
.route("/upload", post(upload_attachment).layer(axum::extract::DefaultBodyLimit::max(10 * 1024 * 1024 * 1024)))
|
||||||
.route("/delete/{id}", post(delete_attachment))
|
.route("/delete/{id}", post(delete_attachment))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,12 +90,14 @@ pub async fn upload_attachment(
|
|||||||
drop(file);
|
drop(file);
|
||||||
|
|
||||||
// 2. Process image/video in place if needed
|
// 2. Process image/video in place if needed
|
||||||
if content_type.starts_with("image/") {
|
// Only process images smaller than 100MB to avoid OOM
|
||||||
let data = fs::read(&file_path).await.context("Failed to read image")?;
|
if content_type.starts_with("image/") && size < 100 * 1024 * 1024 {
|
||||||
|
if let Ok(data) = fs::read(&file_path).await {
|
||||||
if let Ok(processed_data) = process_image(&data, &content_type).await {
|
if let Ok(processed_data) = process_image(&data, &content_type).await {
|
||||||
fs::write(&file_path, &processed_data).await.context("Failed to overwrite image")?;
|
let _ = fs::write(&file_path, &processed_data).await;
|
||||||
size = processed_data.len() as i64;
|
size = processed_data.len() as i64;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if content_type.starts_with("video/") {
|
} else if content_type.starts_with("video/") {
|
||||||
let p_buf = file_path.clone();
|
let p_buf = file_path.clone();
|
||||||
let _ = tokio::task::spawn_blocking(move || {
|
let _ = tokio::task::spawn_blocking(move || {
|
||||||
@@ -107,7 +109,9 @@ pub async fn upload_attachment(
|
|||||||
}
|
}
|
||||||
}).await;
|
}).await;
|
||||||
|
|
||||||
size = fs::metadata(&file_path).await.context("Failed to get size")?.len() as i64;
|
if let Ok(meta) = fs::metadata(&file_path).await {
|
||||||
|
size = meta.len() as i64;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlx::query("INSERT INTO attachments (id, filename, content_type, size, created_at) VALUES (?, ?, ?, ?, ?)")
|
sqlx::query("INSERT INTO attachments (id, filename, content_type, size, created_at) VALUES (?, ?, ?, ?, ?)")
|
||||||
|
|||||||
@@ -120,7 +120,8 @@ async fn main() {
|
|||||||
.route("/__attachments/{id}", get(handlers::attachments::serve_attachment))
|
.route("/__attachments/{id}", get(handlers::attachments::serve_attachment))
|
||||||
.nest("/__dungeon", handlers::router(&app_state)) // I'll create a single `handlers::router`
|
.nest("/__dungeon", handlers::router(&app_state)) // I'll create a single `handlers::router`
|
||||||
.with_state(app_state.clone())
|
.with_state(app_state.clone())
|
||||||
.layer(axum::extract::DefaultBodyLimit::disable())
|
.layer(axum::extract::DefaultBodyLimit::max(10 * 1024 * 1024 * 1024)) // 10GB limit to be safe
|
||||||
|
|
||||||
.layer(tower_http::trace::TraceLayer::new_for_http());
|
.layer(tower_http::trace::TraceLayer::new_for_http());
|
||||||
|
|
||||||
let listener = TcpListener::bind(&addr).await.unwrap();
|
let listener = TcpListener::bind(&addr).await.unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user