use anyhow::Result;
use async_graphql::Request as GraphQlRequest;
use lambda_http::Request;
use multer::Multipart;
use std::io::Cursor;
use tokio_util::codec::{BytesCodec, FramedRead};
#[derive(Debug, Clone)]
pub struct UploadedFile {
pub filename: String,
pub content_type: Option<String>,
pub content: Vec<u8>,
}
pub async fn parse_multipart(request: Request) -> Result<GraphQlRequest> {
let content_type = request
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.ok_or_else(|| anyhow::anyhow!("Missing content-type"))?;
let boundary = multer::parse_boundary(content_type)
.map_err(|e| anyhow::anyhow!("Failed to parse boundary: {}", e))?;
let body_bytes = request.body().to_vec();
let cursor = Cursor::new(body_bytes);
let stream = FramedRead::new(cursor, BytesCodec::new());
let mut multipart = Multipart::new(stream, boundary);
let mut operations: Option<GraphQlRequest> = None;
while let Some(field) = multipart
.next_field()
.await
.map_err(|e| anyhow::anyhow!("{}", e))?
{
let name = field.name().unwrap_or("").to_string();
if name == "operations" {
let text = field.text().await.map_err(|e| anyhow::anyhow!("{}", e))?;
operations =
Some(serde_json::from_str(&text).map_err(|e| anyhow::anyhow!("{}", e))?);
}
}
operations.ok_or_else(|| anyhow::anyhow!("Missing operations"))
}