use Request;
use RouteError;
use std::io::Cursor;
use std::mem;
use multipart::server::Multipart as InnerMultipart;
pub use multipart::server::MultipartField;
pub use multipart::server::MultipartData;
pub use multipart::server::MultipartFile;
#[derive(Clone, Debug)]
pub enum MultipartError {
WrongContentType,
}
impl From<MultipartError> for RouteError {
#[inline]
fn from(err: MultipartError) -> RouteError {
RouteError::WrongInput
}
}
pub fn get_multipart_input(request: &Request) -> Result<Multipart, MultipartError> {
let boundary = match multipart_boundary(request) {
Some(b) => b,
None => return Err(MultipartError::WrongContentType)
};
Ok(Multipart {
inner: InnerMultipart::with_body(Cursor::new(request.data()), boundary)
})
}
pub struct Multipart {
inner: InnerMultipart<Cursor<Vec<u8>>>
}
impl Multipart {
pub fn next(&mut self) -> Option<MultipartField<Cursor<Vec<u8>>>> {
match self.inner.read_entry() {
Ok(e) => e,
_ => return None
}
}
}
fn multipart_boundary(request: &Request) -> Option<String> {
const BOUNDARY: &'static str = "boundary=";
let content_type = match request.header("Content-Type") {
None => return None,
Some(c) => c
};
let start = match content_type.find(BOUNDARY) {
Some(pos) => pos + BOUNDARY.len(),
None => return None
};
let end = content_type[start..].find(';').map_or(content_type.len(), |end| start + end);
Some(content_type[start .. end].to_owned())
}