mirror of https://github.com/fafhrd91/actix-web
Content-Disposition header is required in multipart
This commit is contained in:
parent
b75b5114c3
commit
51b705a629
|
@ -72,7 +72,7 @@ impl<'a> From<&'a str> for DispositionType {
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum DispositionParam {
|
pub enum DispositionParam {
|
||||||
/// For [`DispositionType::FormData`] (i.e. *multipart/form-data*), the name of an field from
|
/// For [`DispositionType::FormData`] (i.e. *multipart/form-data*), the name of a field from
|
||||||
/// the form.
|
/// the form.
|
||||||
Name(String),
|
Name(String),
|
||||||
/// A plain file name.
|
/// A plain file name.
|
||||||
|
|
|
@ -10,6 +10,9 @@ pub enum MultipartError {
|
||||||
/// Content-Type header is not found
|
/// Content-Type header is not found
|
||||||
#[display(fmt = "No Content-type header found")]
|
#[display(fmt = "No Content-type header found")]
|
||||||
NoContentType,
|
NoContentType,
|
||||||
|
/// Content-Disposition header satisfying RFC7578 is not found (see https://tools.ietf.org/html/rfc7578#section-4.2)
|
||||||
|
#[display(fmt = "No content-disposition header satisfying RFC7578 found")]
|
||||||
|
NoContentDisposition,
|
||||||
/// Can not parse Content-Type header
|
/// Can not parse Content-Type header
|
||||||
#[display(fmt = "Can not parse Content-Type header")]
|
#[display(fmt = "Can not parse Content-Type header")]
|
||||||
ParseContentType,
|
ParseContentType,
|
||||||
|
|
|
@ -13,7 +13,10 @@ use futures_util::stream::{LocalBoxStream, Stream, StreamExt};
|
||||||
|
|
||||||
use actix_utils::task::LocalWaker;
|
use actix_utils::task::LocalWaker;
|
||||||
use actix_web::error::{ParseError, PayloadError};
|
use actix_web::error::{ParseError, PayloadError};
|
||||||
use actix_web::http::header::{self, ContentDisposition, HeaderMap, HeaderName, HeaderValue};
|
use actix_web::http::header::{
|
||||||
|
self, ContentDisposition, DispositionParam, DispositionType, HeaderMap, HeaderName,
|
||||||
|
HeaderValue,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::error::MultipartError;
|
use crate::error::MultipartError;
|
||||||
|
|
||||||
|
@ -402,14 +405,28 @@ impl Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the content disposition of the field, if it exists
|
/// Get the content disposition of the field, if it exists
|
||||||
pub fn content_disposition(&self) -> Option<ContentDisposition> {
|
pub fn content_disposition(&self) -> Result<ContentDisposition, MultipartError> {
|
||||||
// RFC 7578: 'Each part MUST contain a Content-Disposition header field
|
// RFC 7578: 'Each part MUST contain a Content-Disposition header field
|
||||||
// where the disposition type is "form-data".'
|
// where the disposition type is "form-data". The Content-Disposition
|
||||||
if let Some(content_disposition) = self.headers.get(&header::CONTENT_DISPOSITION) {
|
// header field MUST also contain an additional parameter of "name"; the
|
||||||
ContentDisposition::from_raw(content_disposition).ok()
|
// value of the "name" parameter is the original field name from the
|
||||||
} else {
|
// form.
|
||||||
None
|
self.headers
|
||||||
}
|
.get(&header::CONTENT_DISPOSITION)
|
||||||
|
.and_then(|content_disposition| {
|
||||||
|
ContentDisposition::from_raw(content_disposition).ok()
|
||||||
|
})
|
||||||
|
.filter(|content_disposition| {
|
||||||
|
content_disposition.disposition == DispositionType::FormData
|
||||||
|
&& content_disposition
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.any(|param| match param {
|
||||||
|
DispositionParam::Name(_) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.ok_or(MultipartError::NoContentDisposition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue