axum icon indicating copy to clipboard operation
axum copied to clipboard

Parse multipart body into a struct like Json<SomeStruct>

Open affanshahid opened this issue 2 years ago • 1 comments

Feature Request

Motivation

Similar to how a request body can be parsed into struct from Json, it would be useful to have an extractor to do the same for multipart requests. Currently the extractor needs used manually to read individual fields

Proposal

A new extractor perhaps

Alternatives

Currently I will need to do this in user code

affanshahid avatar Oct 15 '22 13:10 affanshahid

Can you explain what you use case is for this?

davidpdrsn avatar Oct 15 '22 13:10 davidpdrsn

For future readers, here is how to do it today:

async fn upload_json(mut multipart: Multipart) -> Result<(), StatusCode> {
    #[derive(serde::Deserialize)]
    struct Payload {
        foo: String,
    }

    while let Some(field) = multipart
        .next_field()
        .await
        .map_err(|_| StatusCode::BAD_REQUEST)?
    {
        // might also wanna check `field.name()`, `field.file_name()`, or `field.headers()`

        let bytes = field.bytes().await.map_err(|_| StatusCode::BAD_REQUEST)?;

        let payload: Payload =
            serde_json::from_slice(&bytes).map_err(|_| StatusCode::BAD_REQUEST)?;
    }

    Ok(())
}

Since you need to check the name, etc, I'm not sure how to make this simpler or if doing so is worth it.

davidpdrsn avatar Oct 16 '22 09:10 davidpdrsn

I think a Form equivalent for multipart forms, if we add it at all, should come with a big warning that it should only be used when the fields are pretty small / you need to hold them all in memory at once anyways, as the existing Multipart extractor is much more efficient when passing through the fields to some output in a streaming manner is possible, or when multiple large fields can be handled individually.

jplatte avatar Oct 16 '22 10:10 jplatte

I'll close this for now. Not clear what the use case is so @affanshahid please comment if you can provide more context.

davidpdrsn avatar Oct 20 '22 16:10 davidpdrsn

I'd like to chime in, because this is something that's biting me at work currently.

In other frameworks (Spring Boot with Java comes to mind personally) it is possible and fairly common to map all the fields of a multipart/form-data body to a single object.

It is of course a tradeoff and the current extractor is admittedly much more efficient, but reading, validating and parsing every field can get a little too verbose when dealing with more than a couple of fields.

ariSunz avatar Nov 02 '22 12:11 ariSunz

Nothing is stopping you from writing your own though.

jplatte avatar Nov 02 '22 12:11 jplatte

Oh yeah, of course (and now I'm curious to try that out). I was just saying it's a usecase I've seen often enough.

ariSunz avatar Nov 02 '22 12:11 ariSunz