flyer 2.5.1

HTTP framework for rust
Documentation
use anyhow::Result;
use bytes::Bytes;
use multer::{Field, Multipart};
use tokio_util::io::ReaderStream;

use crate::{
    request::{Request, form::File},
    utils::url::parse_query_params
};

pub(crate) async fn parse_content_type(req: &mut Request) -> Result<()> {
    match req.content_type().as_str() {
        "application/x-www-form-urlencoded" => parse_form_urlencoded( req).await.unwrap(),
        "multipart/form-data" => parse_multipart_form(req).await.unwrap(),
        _ => {}
    }

    if let Some(method) =  req.form.values.get("__METHOD__") {
        req.method = method.to_uppercase();
    }

    return Ok(());
}

pub(crate) fn get_multipart_header_boundary(header: String) -> std::io::Result<String> {
    let content_type: Vec<&str> = header.split(";").collect();
    let content_type_piece = content_type.get(1).unwrap().to_string();
    let boundary =   parse_query_params(content_type_piece.trim())
        .get("boundary")
        .unwrap()
        .to_string();
    
    return Ok(boundary);
}

async fn parse_multipart_form(req: &mut Request) -> Result<()> {
    let boundary = get_multipart_header_boundary(req.header("content-type")).unwrap();
    let body = req.body.clone();
    let stream = ReaderStream::new(body.as_slice());
    let mut multipart = Multipart::new(stream,  boundary);

    while let Some(field) = multipart.next_field().await.or::<Result<Option<Field>>>(Ok(None)).unwrap() {
        if field.file_name().is_none() {
            req.form.values.insert(
                field.name().as_mut().unwrap().to_string(),
                field.text().await.or::<Result<String>>(Ok("".to_string())).unwrap().to_string(),
            );

            continue;
        }

        let name = field.name().as_mut().unwrap().to_string();
        let filename = field.file_name().as_mut().unwrap().to_string();
        let content_type = field.content_type().as_mut().unwrap().to_string();
        let data = field.bytes().await.as_mut().or::<&mut Bytes>(Ok(&mut bytes::Bytes::new())).unwrap().to_vec();
        
        if data.len() == 0 {
            continue;
        }

        req.form.files.insert(name, File::new(filename.as_str(), content_type.as_str(), data));
    }

    return Ok(());
}

async fn parse_form_urlencoded(req: &mut Request) -> std::io::Result<()> {
    let values = parse_query_params(String::from_utf8(req.body.clone()).unwrap().as_str());

    for (k, v) in values {
        req.form.values.insert(k, v);
    }

    return Ok(());
}