nabla_cli/routes/
debug.rs1use crate::AppState;
3use axum::{
4 extract::{Multipart, State},
5 http::StatusCode,
6 response::Json,
7};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Serialize, Deserialize)]
11pub struct MultipartDebugInfo {
12 pub fields: Vec<FieldInfo>,
13 pub total_fields: usize,
14}
15
16#[derive(Debug, Serialize, Deserialize)]
17pub struct FieldInfo {
18 pub field_name: String,
19 pub filename: Option<String>,
20 pub content_type: Option<String>,
21 pub size_bytes: usize,
22 pub content_preview: String,
23}
24
25pub async fn debug_multipart(
26 State(_state): State<AppState>,
27 mut multipart: Multipart,
28) -> Result<Json<MultipartDebugInfo>, StatusCode> {
29 let mut fields = Vec::new();
30
31 while let Some(field) = multipart
32 .next_field()
33 .await
34 .map_err(|_| StatusCode::BAD_REQUEST)?
35 {
36 let field_name = field.name().unwrap_or("unknown").to_string();
37 let filename = field.file_name().map(|s| s.to_string());
38 let content_type = field.content_type().map(|s| s.to_string());
39
40 let contents = field.bytes().await.map_err(|_| StatusCode::BAD_REQUEST)?;
41 let size_bytes = contents.len();
42
43 let content_preview = if contents.len() <= 100 {
45 String::from_utf8_lossy(&contents).to_string()
46 } else {
47 format!(
48 "{}... (truncated)",
49 String::from_utf8_lossy(&contents[..100])
50 )
51 };
52
53 fields.push(FieldInfo {
54 field_name,
55 filename,
56 content_type,
57 size_bytes,
58 content_preview,
59 });
60 }
61
62 Ok(Json(MultipartDebugInfo {
63 total_fields: fields.len(),
64 fields,
65 }))
66}