seanmonstar / warp

A super-easy, composable, web server framework for warp speeds.
https://seanmonstar.com/post/176530511587/warp
MIT License
9.54k stars 717 forks source link

Extracting HashMap from multipart-form and/or unifying body::form and multipart::form #709

Open juchiast opened 4 years ago

juchiast commented 4 years ago

I'm trying to support both multipart form and normal form, here is a solution that I came up with:

    async fn concat(
        mut parts: warp::multipart::FormData,
    ) -> Result<HashMap<String, String>, warp::Rejection> {
        let mut map = HashMap::new();
        let mut buf = BytesMut::with_capacity(1024);
        while let Some(Ok(part)) = parts.next().await {
            let name = part.name().to_owned();
            buf.clear();
            let mut stream = part.stream();
            while let Some(Ok(data)) = stream.next().await {
                buf.extend_from_slice(data.bytes());
            }
            map.insert(name, String::from_utf8(buf.bytes().to_vec()).unwrap());
        }
        Ok(map)
    }

    let multipart = warp::multipart::form().and_then(concat);
    let form = warp::body::content_length_limit(1024).and(multipart.or(warp::body::form()).unify());

    warp::path("login")
        .and(warp::post())
        .and(form)
        .and_then(verify)

I think it would be beneficial to add this functionality to warp.

seanmonstar commented 4 years ago

I agree it'd be nice to add some helpers to warp::multipart, such as de-serializing using serde. We just would need a proposed API, one which considers the streaming nature of multipart bodies (and providing safe caps so as to not buffer enormous bodies unless allowed).