From 6c90900d4933b4f84463dbfcfb80d973b502425b Mon Sep 17 00:00:00 2001 From: Darius Auding <Darius.auding@gmx.de> Date: Mon, 3 Jul 2023 14:57:00 +0200 Subject: [PATCH] prototyping for cookies further, working on UrlEncoded text --- core/http/src/handling/file_handlers.rs | 2 +- core/http/src/handling/request/cookies.rs | 1 + core/http/src/handling/request/datatypes.rs | 4 +- core/http/src/handling/request/form_utils.rs | 4 +- .../http/src/handling/request/request_mime.rs | 4 +- .../response/cookie_management/cookie.rs | 18 +++ .../cookie_management/cookie_builder.rs | 5 + core/http/src/handling/response/traits.rs | 2 +- core/http/src/handling/routes.rs | 2 +- core/http/src/utils/mime/mod.rs | 5 +- core/http/src/utils/mod.rs | 1 + core/http/src/utils/urlencoded/datatypes.rs | 26 ++++ core/http/src/utils/urlencoded/endecode.rs | 140 ++++++++++++++++++ core/http/src/utils/urlencoded/mod.rs | 2 + 14 files changed, 206 insertions(+), 10 deletions(-) create mode 100644 core/http/src/utils/urlencoded/datatypes.rs create mode 100644 core/http/src/utils/urlencoded/endecode.rs create mode 100644 core/http/src/utils/urlencoded/mod.rs diff --git a/core/http/src/handling/file_handlers.rs b/core/http/src/handling/file_handlers.rs index 8ca0019..7a0b080 100644 --- a/core/http/src/handling/file_handlers.rs +++ b/core/http/src/handling/file_handlers.rs @@ -2,7 +2,7 @@ use std::{fs, path::PathBuf}; use crate::{ handling::response::{ResponseBody, Status}, - utils::mime::mime_enum::Mime, + utils::mime::Mime, }; #[derive(Debug)] diff --git a/core/http/src/handling/request/cookies.rs b/core/http/src/handling/request/cookies.rs index b386086..cd3c4ca 100644 --- a/core/http/src/handling/request/cookies.rs +++ b/core/http/src/handling/request/cookies.rs @@ -52,6 +52,7 @@ impl Request<'_> { .strip_prefix("Cookie: ") .unwrap() .trim() + .trim_matches('"') .to_string(); for cookie in cookies_string.split(';') { let Some((name, cookie)) = cookie.split_once('=') else { diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs index acde6d8..df96177 100644 --- a/core/http/src/handling/request/datatypes.rs +++ b/core/http/src/handling/request/datatypes.rs @@ -1,8 +1,8 @@ -use std::{borrow::Cow, collections::HashMap, error::Error, fmt::Display}; +use std::{collections::HashMap, error::Error, fmt::Display}; use crate::{ handling::{methods::Method, routes::Uri}, - utils::mime::mime_enum::Mime, + utils::mime::Mime, }; pub trait FromRequest: Send { diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs index cab16eb..9aa300c 100644 --- a/core/http/src/handling/request/form_utils.rs +++ b/core/http/src/handling/request/form_utils.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::{handling::routes::Data, utils::mime::mime_enum::Mime}; +use crate::{handling::routes::Data, utils::mime::Mime}; use super::{datatypes::ParseErrors, ParseFormError, Request}; static TWO_NEWLINES: u8 = 3; @@ -239,7 +239,7 @@ mod test { request::{datatypes::ParseErrors, ParseFormError}, routes::Data, }, - utils::mime::mime_enum::Mime::{ApplicationXWwwFormUrlencoded, MultipartFormData}, + utils::mime::Mime::{ApplicationXWwwFormUrlencoded, MultipartFormData}, }; use super::Request; diff --git a/core/http/src/handling/request/request_mime.rs b/core/http/src/handling/request/request_mime.rs index 7551bb7..56188d1 100644 --- a/core/http/src/handling/request/request_mime.rs +++ b/core/http/src/handling/request/request_mime.rs @@ -9,7 +9,7 @@ impl<'a> Request<'a> { /// ``` /// use http::{ /// handling::{methods::Method, request::Request}, - /// utils::mime::mime_enum::Mime, + /// utils::mime::Mime, /// }; /// /// let mut request = Request { @@ -71,7 +71,7 @@ impl<'a> Request<'a> { mod test { use crate::{ handling::{methods::Method, request::Request}, - utils::mime::mime_enum::Mime, + utils::mime::Mime, }; #[test] diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs index cfe3501..4e072eb 100644 --- a/core/http/src/handling/response/cookie_management/cookie.rs +++ b/core/http/src/handling/response/cookie_management/cookie.rs @@ -19,10 +19,28 @@ pub struct Cookie<'a> { /// The draft `SameSite` attribute. pub(crate) same_site: Option<SameSite>, pub(crate) expires: Option<&'a str>, + pub(crate) partitioned: Option<bool>, } +#[derive(Debug)] pub enum SameSite { None, Lax, Strict, } + +impl std::fmt::Display for SameSite { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::None => write!(f, "SameSite=None; Secure"), + Self::Lax => write!(f, "SameSite=Lax"), + Self::Strict => write!(f, "SameSite=Strict"), + } + } +} + +impl std::fmt::Display for Cookie<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + todo!() + } +} 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 ead2df0..431160a 100644 --- a/core/http/src/handling/response/cookie_management/cookie_builder.rs +++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs @@ -20,6 +20,7 @@ impl<'a> CookieBuilder<'a> { http_only: None, same_site: None, expires: None, + partitioned: None, }, } } @@ -54,6 +55,10 @@ impl<'a> CookieBuilder<'a> { self.inner.expires = Some(expire); self } + pub fn partitioned(mut self, partitioned: bool) -> Self { + self.inner.partitioned = Some(partitioned); + self + } pub fn name(mut self, name: &'a str) -> Self { self.inner.name = name; self diff --git a/core/http/src/handling/response/traits.rs b/core/http/src/handling/response/traits.rs index 96ac87c..fc7eb09 100644 --- a/core/http/src/handling/response/traits.rs +++ b/core/http/src/handling/response/traits.rs @@ -1,4 +1,4 @@ -use crate::{handling::routes::Body, utils::mime::mime_enum::Mime}; +use crate::{handling::routes::Body, utils::mime::Mime}; pub trait ResponseBody: Send { fn get_data(&self) -> Vec<u8>; diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs index a85261a..e4246b8 100644 --- a/core/http/src/handling/routes.rs +++ b/core/http/src/handling/routes.rs @@ -4,7 +4,7 @@ use crate::{ request::{MediaType, Request}, response::{Outcome, Response, Status}, }, - utils::mime::mime_enum::Mime, + utils::mime::Mime, }; pub struct RoutInfo { diff --git a/core/http/src/utils/mime/mod.rs b/core/http/src/utils/mime/mod.rs index bbf3a87..4421654 100644 --- a/core/http/src/utils/mime/mod.rs +++ b/core/http/src/utils/mime/mod.rs @@ -1,2 +1,5 @@ mod map; -pub mod mime_enum; +mod mime_enum; +pub use map::MIME_MAP; +pub use mime_enum::Mime; +pub use mime_enum::ParseMimeError; diff --git a/core/http/src/utils/mod.rs b/core/http/src/utils/mod.rs index 909a531..98498d0 100644 --- a/core/http/src/utils/mod.rs +++ b/core/http/src/utils/mod.rs @@ -1 +1,2 @@ pub mod mime; +pub mod urlencoded; diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs new file mode 100644 index 0000000..c370ddf --- /dev/null +++ b/core/http/src/utils/urlencoded/datatypes.rs @@ -0,0 +1,26 @@ +use std::borrow::Cow; + +use super::endecode::EnDecodable; + +pub struct UrlEncodeData<'a> { + encoded: Cow<'a, str>, + raw: Cow<'a, str>, +} + +impl UrlEncodeData<'_> { + pub fn from_raw(raw: &str) -> Self { + todo!() + } + pub fn from_encoded(encoded: &str) -> Self { + todo!() + } +} + +impl EnDecodable for UrlEncodeData<'_> { + fn encode(&self) -> Cow<'_, str> { + self.raw.encode() + } + fn decode(&self) -> Result<Cow<'_, str>, ()> { + self.encoded.decode() + } +} diff --git a/core/http/src/utils/urlencoded/endecode.rs b/core/http/src/utils/urlencoded/endecode.rs new file mode 100644 index 0000000..0e7fe2c --- /dev/null +++ b/core/http/src/utils/urlencoded/endecode.rs @@ -0,0 +1,140 @@ +use std::borrow::Cow; + +static BASE16_HEXA_DECIMAL: u8 = 16; +pub trait EnDecodable { + fn encode(&self) -> Cow<'_, str>; + fn decode(&self) -> Result<Cow<'_, str>, ()>; +} + +impl EnDecodable for Cow<'_, str> { + fn encode(&self) -> Cow<'_, str> { + self.bytes() + .map(|byte| { + if !byte.is_ascii_alphanumeric() { + format!("%{:02X}", byte) + } else { + String::from_utf8([byte].to_vec()).unwrap() + } + }) + .collect() + } + fn decode(&self) -> Result<Cow<'_, str>, ()> { + let mut first = true; + let mut result = String::with_capacity(self.len()); + for i in self.split('%') { + if first { + first = false; + result += i; + continue; + } + let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else { + return Err(()); + }; + unsafe { + result.as_mut_vec().push(char); + } + result = result + &i[2..]; + } + Ok(result.into()) + } +} + +impl EnDecodable for &str { + fn encode(&self) -> Cow<'_, str> { + self.bytes() + .map(|byte| { + if !byte.is_ascii_alphanumeric() { + format!("%{:02X}", byte) + } else { + String::from_utf8([byte].to_vec()).unwrap() + } + }) + .collect() + } + + fn decode(&self) -> Result<Cow<'_, str>, ()> { + let mut first = true; + let mut result = String::with_capacity(self.len()); + for i in self.split('%') { + if first { + first = false; + result += i; + continue; + } + let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else { + return Err(()); + }; + unsafe { + result.as_mut_vec().push(char); + } + result = result + &i[2..]; + } + Ok(result.into()) + } +} + +impl EnDecodable for String { + fn encode(&self) -> Cow<'_, str> { + self.bytes() + .map(|byte| { + if !byte.is_ascii_alphanumeric() { + format!("%{:02X}", byte) + } else { + String::from_utf8([byte].to_vec()).unwrap() + } + }) + .collect() + } + fn decode(&self) -> Result<Cow<'_, str>, ()> { + let mut first = true; + let mut result = String::with_capacity(self.len()); + for i in self.split('%') { + if first { + first = false; + result += i; + continue; + } + let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else { + return Err(()); + }; + unsafe { + result.as_mut_vec().push(char); + } + result = result + &i[2..]; + } + Ok(result.into()) + } +} + +#[cfg(test)] +mod test { + use std::borrow::Cow; + + use crate::utils::urlencoded::endecode::EnDecodable; + + #[test] + fn urlencoded_test() { + assert_eq!( + "Darius%20is%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire", + Cow::Borrowed("Darius is the biggest genius/Genie/Human extraordinäire").encode() + ) + } + #[test] + fn urldecoded_test() { + assert_eq!( + "Darius is the biggest genius/Genie/Human extraordinäire", + Cow::Borrowed( + "Darius%20is%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire" + ) + .decode() + .unwrap() + ); + assert_eq!( + Err(()), + Cow::Borrowed( + "Darius%2iis%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire" + ) + .decode() + ); + } +} diff --git a/core/http/src/utils/urlencoded/mod.rs b/core/http/src/utils/urlencoded/mod.rs new file mode 100644 index 0000000..43ea58f --- /dev/null +++ b/core/http/src/utils/urlencoded/mod.rs @@ -0,0 +1,2 @@ +mod datatypes; +mod endecode; -- GitLab