#[cfg(feature = "multipart")]
use super::{FromRequest, ParamContext, ParamError, ParamErrorContext, ParamResult, ParamType};
#[cfg(feature = "multipart")]
use async_trait::async_trait;
#[cfg(feature = "multipart")]
use futures_util::future::ready;
#[cfg(feature = "multipart")]
use futures_util::stream::once;
#[cfg(feature = "multipart")]
use reinhardt_http::Request;
#[cfg(feature = "multipart")]
pub use multer::{Field, Multipart as MulterMultipart};
#[cfg(feature = "multipart")]
pub struct Multipart(pub MulterMultipart<'static>);
#[cfg(feature = "multipart")]
impl Multipart {
pub async fn next_field(&mut self) -> Result<Option<Field<'static>>, multer::Error> {
self.0.next_field().await
}
}
#[cfg(feature = "multipart")]
#[async_trait]
impl FromRequest for Multipart {
async fn from_request(req: &Request, _ctx: &ParamContext) -> ParamResult<Self> {
let content_type = req
.headers
.get(http::header::CONTENT_TYPE)
.and_then(|v| v.to_str().ok())
.ok_or_else(|| {
ParamError::InvalidParameter(Box::new(
ParamErrorContext::new(
ParamType::Header,
"Missing Content-Type header".to_string(),
)
.with_field("content-type"),
))
})?;
let boundary = multer::parse_boundary(content_type).map_err(|e| {
ParamError::InvalidParameter(Box::new(
ParamErrorContext::new(
ParamType::Header,
format!("Failed to parse boundary: {}", e),
)
.with_field("content-type"),
))
})?;
let body = req
.read_body()
.map_err(|e| ParamError::BodyError(format!("Failed to read body: {}", e)))?;
let stream = once(ready(Ok::<_, std::io::Error>(body)));
let multipart = MulterMultipart::new(stream, boundary);
Ok(Multipart(multipart))
}
}