P2: Fix S3 multipart route - use query param for action
- Change route from /s3/multipart/:bucket/*key/init to /s3/multipart/:bucket/*key?action=init - Add multipart_handler to unify all multipart operations - Use Response type instead of impl IntoResponse for type compatibility
This commit is contained in:
@@ -1027,3 +1027,79 @@ fn extract_user_from_auth(headers: &HeaderMap) -> Option<String> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unified multipart handler using query param for action
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct MultipartActionQuery {
|
||||||
|
action: Option<String>, // init, part, complete, abort
|
||||||
|
upload_id: Option<String>,
|
||||||
|
part_number: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn multipart_handler(
|
||||||
|
method: axum::http::Method,
|
||||||
|
Path((bucket, key)): Path<(String, String)>,
|
||||||
|
State(state): State<crate::server::AppState>,
|
||||||
|
query: axum::extract::Query<MultipartActionQuery>,
|
||||||
|
headers: HeaderMap,
|
||||||
|
body: Body,
|
||||||
|
) -> axum::response::Response {
|
||||||
|
let action = query.action.as_deref().unwrap_or("");
|
||||||
|
|
||||||
|
match action {
|
||||||
|
"init" => {
|
||||||
|
initiate_multipart_upload(
|
||||||
|
Path((bucket, key)),
|
||||||
|
State(state),
|
||||||
|
headers,
|
||||||
|
).await.into_response()
|
||||||
|
}
|
||||||
|
"part" => {
|
||||||
|
let upload_query = axum::extract::Query(UploadPartQuery {
|
||||||
|
upload_id: query.upload_id.clone().unwrap_or_default(),
|
||||||
|
part_number: query.part_number.unwrap_or(1),
|
||||||
|
});
|
||||||
|
upload_part(
|
||||||
|
Path((bucket, key)),
|
||||||
|
State(state),
|
||||||
|
upload_query,
|
||||||
|
headers,
|
||||||
|
body,
|
||||||
|
).await.into_response()
|
||||||
|
}
|
||||||
|
"complete" => {
|
||||||
|
let complete_query = axum::extract::Query(CompleteMultipartQuery {
|
||||||
|
upload_id: query.upload_id.clone().unwrap_or_default(),
|
||||||
|
});
|
||||||
|
complete_multipart_upload(
|
||||||
|
Path((bucket, key)),
|
||||||
|
State(state),
|
||||||
|
complete_query,
|
||||||
|
headers,
|
||||||
|
body,
|
||||||
|
).await.into_response()
|
||||||
|
}
|
||||||
|
"abort" => {
|
||||||
|
let abort_query = axum::extract::Query(AbortMultipartQuery {
|
||||||
|
upload_id: query.upload_id.clone().unwrap_or_default(),
|
||||||
|
});
|
||||||
|
abort_multipart_upload(
|
||||||
|
Path((bucket, key)),
|
||||||
|
State(state),
|
||||||
|
abort_query,
|
||||||
|
headers,
|
||||||
|
).await.into_response()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if method == axum::http::Method::POST {
|
||||||
|
initiate_multipart_upload(
|
||||||
|
Path((bucket, key)),
|
||||||
|
State(state),
|
||||||
|
headers,
|
||||||
|
).await.into_response()
|
||||||
|
} else {
|
||||||
|
(StatusCode::BAD_REQUEST, "Missing action parameter").into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -245,11 +245,12 @@ pub async fn run(port: u16, file: Option<String>) -> anyhow::Result<()> {
|
|||||||
.post(crate::s3::put_object) // POST for uploads (same handler handles multipart detection)
|
.post(crate::s3::put_object) // POST for uploads (same handler handles multipart detection)
|
||||||
.delete(crate::s3::delete_object)
|
.delete(crate::s3::delete_object)
|
||||||
)
|
)
|
||||||
// Multipart upload endpoints
|
// Multipart upload endpoints (use query param for action)
|
||||||
.route("/s3/multipart/:bucket/*key/init", post(crate::s3::initiate_multipart_upload))
|
.route("/s3/multipart/:bucket/*key",
|
||||||
.route("/s3/multipart/:bucket/*key/part", put(crate::s3::upload_part))
|
post(crate::s3::multipart_handler)
|
||||||
.route("/s3/multipart/:bucket/*key/complete", post(crate::s3::complete_multipart_upload))
|
.put(crate::s3::multipart_handler)
|
||||||
.route("/s3/multipart/:bucket/*key/abort", delete(crate::s3::abort_multipart_upload))
|
.delete(crate::s3::multipart_handler)
|
||||||
|
)
|
||||||
// Bucket policy endpoints
|
// Bucket policy endpoints
|
||||||
.route("/s3/policy/:bucket", get(crate::s3::get_bucket_policy))
|
.route("/s3/policy/:bucket", get(crate::s3::get_bucket_policy))
|
||||||
.route("/s3/policy/:bucket", put(crate::s3::put_bucket_policy))
|
.route("/s3/policy/:bucket", put(crate::s3::put_bucket_policy))
|
||||||
|
|||||||
Reference in New Issue
Block a user