nabla_cli/routes/
debug.rs

1// Debug route for multipart analysis
2use 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        // Create a safe preview of the content
44        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}