diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs index bbb5ac3ac4f83e2f4ed556342a3d69eafaadb1a6..6de43e0110acb05295b67b5e800c4cb0aef4dfa6 100644 --- a/core/http/src/handling/response/cookie_management/cookie.rs +++ b/core/http/src/handling/response/cookie_management/cookie.rs @@ -1,5 +1,7 @@ use std::{error::Error, str::FromStr, time::Duration}; +use crate::{handling::response::CookieBuilder, utils::urlencoded::DeCodable}; + /// Structure representing a Cookie /// # Creating a Cookie: /// ``` @@ -8,6 +10,7 @@ use std::{error::Error, str::FromStr, time::Duration}; /// /// let cookie = CookieBuilder::build("name", "value").finish(); /// ``` +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct Cookie { /// Storage for the cookie string. Only used if this structure was derived /// from a string that was subsequently parsed. @@ -93,6 +96,7 @@ pub struct ParseCookieError { #[derive(Debug, PartialEq, PartialOrd, Eq, Ord)] pub enum CookieError { MissingEqual, + InvalidAttribute, } impl std::fmt::Display for ParseCookieError { @@ -104,7 +108,44 @@ impl std::fmt::Display for ParseCookieError { impl FromStr for Cookie { type Err = ParseCookieError; fn from_str(s: &str) -> Result<Self, Self::Err> { - todo!() + let mut final_result = CookieBuilder::build("", ""); + let mut first = true; + for part in s.split(';') { + let trimmed_part = part.trim(); + if first { + let Some(name_val) = part.split_once('=') else { + return Err(Self::Err { inner: CookieError::MissingEqual }); + }; + unsafe { + final_result = CookieBuilder::build( + &String::from_utf8_unchecked(if let Ok(name) = name_val.0.decode() { + name + } else { + name_val.0.into() + }), + &String::from_utf8_unchecked(if let Ok(value) = name_val.1.decode() { + value + } else { + name_val.1.into() + }), + ); + } + first = false; + break; + } + final_result = match trimmed_part { + "Secure" => final_result.secure(true), + "HttpOnly" => final_result.http_only(true), + "Partitioned" => final_result.partitioned(true), + _ => { + return Err(Self::Err { + inner: CookieError::InvalidAttribute, + }); + } + } + } + println!("{:?}", final_result); + Ok(final_result.finish()) } } @@ -112,7 +153,7 @@ impl FromStr for Cookie { mod test { use std::time::Duration; - use crate::handling::response::CookieBuilder; + use crate::handling::response::{Cookie, CookieBuilder}; use super::SameSite; @@ -133,13 +174,16 @@ mod test { .http_only(true) .partitioned(true) .expires("Monday") - .finish() - .to_string(); + .finish(); let test_cookie3_res = "Set-Cookie: ab=ss; HttpOnly; Partitioned; \ - Max-Age=24; Domain=codecraft.com; Path=/; SameSite=None; Secure; Expires=Monday"; + Max-Age=24; Domain=codecraft.com; Path=%2F; SameSite=None; Secure; Expires=Monday"; + + let test_cookie4_res = "ab=ss; HttpOnly; Partitioned; \ + Max-Age=24; Domain=codecraft.com; Path=%2F; SameSite=None; Secure; Expires=Monday"; assert_eq!(test_cookie1_res, test_cookie1); assert_eq!(test_cookie2_res, test_cookie2); - assert_eq!(test_cookie3_res, test_cookie3); + assert_eq!(test_cookie3_res, test_cookie3.to_string()); + assert_eq!(test_cookie4_res.parse::<Cookie>().unwrap(), test_cookie3); } } diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs index 41bdc977c1f91f64859db4c2c93a88dadac6b44c..5a3dac31730d2a2366fbd6453417f91e51b82619 100644 --- a/core/http/src/handling/response/cookie_management/cookie_builder.rs +++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs @@ -13,6 +13,7 @@ use super::{Cookie, SameSite}; /// /// let cookie = CookieBuilder::build("name", "value").path("/").finish(); /// ``` +#[derive(Debug)] pub struct CookieBuilder { /// Cookie under the hood inner: Cookie, diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs index cbb24c2d865732fab9db0a6da812b28948efa7c6..2db1e181a567379f8adf2d98b4dc6a0bf8923c84 100644 --- a/core/http/src/utils/urlencoded/datatypes.rs +++ b/core/http/src/utils/urlencoded/datatypes.rs @@ -18,7 +18,7 @@ impl UrlEncodeData { pub fn from_raw<T: AsRef<[u8]>>(raw: T) -> Self { Self { raw: raw.as_ref().to_owned(), - encoded: raw.as_ref().encode(), + encoded: raw.encode(), raw_string: String::from_utf8(raw.as_ref().into()).ok(), } } @@ -45,7 +45,7 @@ impl UrlEncodeData { } /// Gets an Optional string slice to the raw data pub fn raw_string(&self) -> Option<&str> { - self.raw_string.as_ref().map(|x| x.as_str()) + self.raw_string.as_deref() } }