seanmonstar/warp

Part::content_type only returns the media type, not the subtype

Pikrass opened this issue · 1 comments

Version
0.3.5

Platform
Linux 6.1.0-6-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.15-1 (2023-03-05) x86_64 GNU/Linux
(but not relevant here)

Description
I'm using the warp::multipart::form filter.
When parsing the returned FormData, the part's content_type method only returns the media type (that is for instance "image" instead of "image/jpeg").

Snippet of my code:

pub async fn parse_multipart(mut form: FormData) -> Result<(), Rejection> {
    let rej = || warp::reject::custom(crate::endpoints::BadRequest);

    while let Some(Ok(part)) = form.next().await {
        let name = String::from(part.name());
        let content_type = part.content_type().map(|s| String::from(s));

        let data: Vec<u8> = part
            .stream()
            .map_err(|_| ())
            .map_ok(|buf|
                stream::iter(
                    buf.reader().bytes().map(|b| Result::<u8, ()>::Ok(b.unwrap()))
                )
            )
            .try_flatten()
            .try_collect()
            .await
            .or(Err(rej()))?;

        // [Do something with name, content_type and data]
    }

    Ok(()) // Return actual data instead
}

The content_type variable on line 6 gets set to eg "image" instead of "image/jpeg".

Relevant code in warp:

/// Get the content-type of this part, if present.
pub fn content_type(&self) -> Option<&str> {
let content_type = self.part.content_type();
content_type.map(|t| t.type_().as_str())
}

Here self.part is a multer::Field. It content_type method returns a Mime. The Mime::type_ method only returns the "toplevel media type".

We need a new method to return the whole Mime struct.
Also the current Part::content_type should probably be changed to return t.to_string() instead (or t.essence_str()).

Workaround
For now, I just deduce the full MIME type from the filename instead.

Oh good catch. I agree, that should be changed to just return the full mime.as_ref().