Skip to content
Snippets Groups Projects
Commit af4ab2e3 authored by codecraft's avatar codecraft :crocodile:
Browse files

refactoring the request module,

add cookie functionality
parent 31f29ad0
No related branches found
No related tags found
1 merge request!1Initial feature merge
......@@ -4,7 +4,7 @@ use tokio::{io::{AsyncReadExt, BufReader, AsyncBufReadExt, AsyncWriteExt}, net::
use crate::handling::{
file_handlers::NamedFile,
request::Request,
request::{Request, extract_cookies_from_vec},
response::{Outcome, Response, ResponseBody, Status},
routes::Data, methods::Method,
};
......@@ -42,7 +42,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
return;
},
cookies: None,
cookies: extract_cookies_from_vec(&mut http_request),
headers: http_request,
method: if let Some(method) = request_status_line
.split(" ")
......
use std::collections::HashMap;
pub fn extract_cookies_from_vec(headers: &mut Vec<String>) -> Option<HashMap<String, String>> {
let mut cookies: HashMap<String, String> = HashMap::new();
let mut cookies_string = if let Some(index) = headers
.iter()
.position(|header| header.starts_with("Cookie: "))
{
headers.remove(index)
} else {
return None;
};
cookies_string = cookies_string
.strip_prefix("Cookie: ")
.unwrap()
.trim()
.to_string();
for cookie in cookies_string.split(';') {
let Some((name, cookie)) = cookie.split_once('=') else {
return None;
};
cookies
.entry(name.trim().to_string())
.or_insert(cookie.trim().to_string());
}
Some(cookies)
}
#[cfg(test)]
mod test {
use crate::handling::request::extract_cookies_from_vec;
#[test]
fn test_cookies() {
let mut request_vec = vec![
"GET / HTTP/1.1".to_string(),
"Accept: sdf".to_string(),
"Cookie: io=23; f=as".to_string(),
"Format: gzip".to_string(),
];
let right_finished_vec = vec![
"GET / HTTP/1.1".to_string(),
"Accept: sdf".to_string(),
"Format: gzip".to_string(),
];
let mut wrong = vec!["GET / HTTP/1.1".to_string()];
assert_eq!(None, extract_cookies_from_vec(&mut wrong));
let cookies = extract_cookies_from_vec(&mut request_vec);
assert_eq!(right_finished_vec, request_vec);
assert_eq!("23", cookies.clone().unwrap().get("io").unwrap());
assert_eq!("as", cookies.unwrap().get("f").unwrap());
}
}
use std::{collections::HashMap, error::Error, fmt::Display};
use crate::handling::{methods::Method, routes::Uri};
pub trait FromRequest: Send {
fn get_data(&self) -> &Self;
fn set_data(&mut self, data: &Self);
fn append(&mut self, data: &Self);
}
impl FromRequest for Vec<u8> {
fn get_data(&self) -> &Self {
&self
}
fn set_data(&mut self, data: &Self) {
*self = data.to_vec();
}
fn append(&mut self, data: &Self) {
self.extend_from_slice(data);
}
}
type HeaderMap = Vec<String>;
#[derive(Clone)]
pub struct Request<'a> {
pub uri: Uri<'a>,
pub headers: HeaderMap,
pub method: Method,
pub cookies: Option<HashMap<String, String>>,
// pub connection: ConnectionMeta,
}
// struct ConnectionMeta {
// remote: Option<SocketAddr>,
// // certificates
// }
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum MediaType {
Json,
Plain,
Html,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum ParseErrors {
NoData,
BadData,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ParseFormError {
pub error: ParseErrors,
}
impl Display for ParseFormError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.error)
}
}
impl Display for ParseErrors {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParseErrors::NoData => write!(f, "No Data at key"),
ParseErrors::BadData => write!(f, "Bad Data at key"),
}
}
}
impl Error for ParseFormError {}
mod cookies;
mod datatypes;
mod request_impl;
pub use cookies::extract_cookies_from_vec;
pub use datatypes::{MediaType, ParseFormError, Request};
// use std::net::SocketAddr;
use std::{collections::HashMap, error::Error, fmt::Display};
use std::collections::HashMap;
use crate::utils::mime::mime_enum::Mime;
static TWO_NEWLINES: u8 = 3;
use super::{
methods::Method,
routes::{Data, Uri},
use crate::{
handling::{methods::Method, routes::Data},
utils::mime::mime_enum::Mime,
};
pub trait FromRequest: Send {
fn get_data(&self) -> &Self;
fn set_data(&mut self, data: &Self);
fn append(&mut self, data: &Self);
}
impl FromRequest for Vec<u8> {
fn get_data(&self) -> &Self {
&self
}
fn set_data(&mut self, data: &Self) {
*self = data.to_vec();
}
fn append(&mut self, data: &Self) {
self.extend_from_slice(data);
}
}
type HeaderMap = Vec<String>;
#[derive(Clone)]
pub struct Request<'a> {
pub uri: Uri<'a>,
pub headers: HeaderMap,
pub method: Method,
pub cookies: Option<Vec<&'a str>>,
// pub connection: ConnectionMeta,
}
// struct ConnectionMeta {
// remote: Option<SocketAddr>,
// // certificates
// }
use super::datatypes::{ParseErrors, ParseFormError, Request};
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum MediaType {
Json,
Plain,
Html,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum ParseErrors {
NoData,
BadData,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ParseFormError {
pub error: ParseErrors,
}
impl Display for ParseFormError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.error)
}
}
impl Display for ParseErrors {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParseErrors::NoData => write!(f, "No Data at key"),
ParseErrors::BadData => write!(f, "Bad Data at key"),
}
}
}
impl Error for ParseFormError {}
static TWO_NEWLINES: u8 = 3;
impl Request<'_> {
pub fn can_have_body(&self) -> bool {
......@@ -98,7 +28,7 @@ impl Request<'_> {
&'a self,
keys: &'a [&str],
) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
let data = if let Some(val) = self.uri.split_once("?") {
let data = if let Some(val) = self.uri.split_once('?') {
val
} else {
return Err(ParseFormError {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment