diff --git a/core/lib/src/request/form/from_form_value.rs b/core/lib/src/request/form/from_form_value.rs index c6e94af5..60b47337 100644 --- a/core/lib/src/request/form/from_form_value.rs +++ b/core/lib/src/request/form/from_form_value.rs @@ -243,7 +243,24 @@ impl_with_fromstr!( f32, f64, isize, i8, i16, i32, i64, i128, usize, u8, u16, u32, u64, u128, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize, - IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr + Ipv4Addr +); + +macro_rules! impl_with_fromstr_encoded { + ($($T:ident),+) => ($( + impl<'v> FromFormValue<'v> for $T { + type Error = &'v RawStr; + + #[inline(always)] + fn from_form_value(v: &'v RawStr) -> Result { + $T::from_str(&v.url_decode().map_err(|_| v)?).map_err(|_| v) + } + } + )+) +} + +impl_with_fromstr_encoded!( + IpAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr ); impl<'v, T: FromFormValue<'v>> FromFormValue<'v> for Option { diff --git a/core/lib/tests/form_value_from_encoded_str-issue-1425.rs b/core/lib/tests/form_value_from_encoded_str-issue-1425.rs new file mode 100644 index 00000000..d1fae2de --- /dev/null +++ b/core/lib/tests/form_value_from_encoded_str-issue-1425.rs @@ -0,0 +1,38 @@ +extern crate rocket; + +use rocket::http::RawStr; +use rocket::request::FromFormValue; +use std::fmt::Debug; +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; + +mod tests { + use super::*; + + fn check_from_form_value_encoded<'a, T>(encoded_str: &'static str, expected: T) + where >::Error: Debug, + T: FromFormValue<'a> + PartialEq + Debug, + { + let value = T::from_form_value(RawStr::from_str(encoded_str)); + + assert!(value.is_ok()); + assert_eq!(value.unwrap(), expected); + } + + #[test] + fn test_from_form_value_encoded() { + check_from_form_value_encoded( + "127.0.0.1%3A80", + SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80), + ); + + check_from_form_value_encoded( + "2001%3A0db8%3A85a3%3A0000%3A0000%3A8a2e%3A0370%3A7334", + Ipv6Addr::new(0x2001, 0x0db8, 0x85a3, 0, 0, 0x8a2e, 0x0370, 0x7334), + ); + + check_from_form_value_encoded( + "%5B2001%3Adb8%3A%3A1%5D%3A8080", + SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0), + ); + } +}