diff --git a/core/lib/src/form/from_form_field.rs b/core/lib/src/form/from_form_field.rs index 69b87f31..9035ad38 100644 --- a/core/lib/src/form/from_form_field.rs +++ b/core/lib/src/form/from_form_field.rs @@ -322,6 +322,27 @@ impl<'v> FromFormField<'v> for bool { } } +#[crate::async_trait] +impl<'v> FromFormField<'v> for Capped<&'v [u8]> { + fn from_value(field: ValueField<'v>) -> Result<'v, Self> { + Ok(Capped::from(field.value.as_bytes())) + } + + async fn from_data(f: DataField<'v, '_>) -> Result<'v, Self> { + use crate::data::{Capped, Outcome, FromData}; + + match as FromData>::from_data(f.request, f.data).await { + Outcome::Success(p) => Ok(p), + Outcome::Failure((_, e)) => Err(e)?, + Outcome::Forward(..) => { + Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))? + } + } + } +} + +impl_strict_from_form_field_from_capped!(&'v [u8]); + #[crate::async_trait] impl<'v> FromFormField<'v> for Capped> { fn from_value(field: ValueField<'v>) -> Result<'v, Self> { diff --git a/core/lib/tests/byte-slices-form-field-issue-2148.rs b/core/lib/tests/byte-slices-form-field-issue-2148.rs new file mode 100644 index 00000000..8fa2ac86 --- /dev/null +++ b/core/lib/tests/byte-slices-form-field-issue-2148.rs @@ -0,0 +1,62 @@ +#[macro_use] extern crate rocket; + +use std::str::from_utf8; + +use rocket::form::Form; +use rocket::http::{ContentType, Status}; +use rocket::local::blocking::Client; + +#[derive(FromForm)] +struct DataForm<'r> { + foo: &'r [u8], + bar: &'r [u8], +} + +#[post("/", data = "
")] +fn form(form: Form>) -> String { + from_utf8(form.foo).unwrap().to_string() + from_utf8(form.bar).unwrap() +} + +#[test] +fn test_from_form_fields_of_multipart_files_into_byte_slices() { + let body = &[ + "--X-BOUNDARY", + r#"Content-Disposition: form-data; name="foo"; filename="foo.txt""#, + "Content-Type: text/plain", + "", + "start>", + "--X-BOUNDARY", + r#"Content-Disposition: form-data; name="foo"; filename="foo2.txt""#, + "Content-Type: text/plain", + "", + "second-start...", + "--X-BOUNDARY", + r#"Content-Disposition: form-data; name="bar"; filename="bar.txt""#, + "Content-Type: text/plain", + "", + "().unwrap()) + .body(body) + .dispatch(); + + assert_eq!(response.status(), Status::Ok); + assert_eq!(response.into_string().unwrap(), "start>