diff --git a/src/main.rs b/src/main.rs
index 77c2b4c..7ff2561 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,34 +5,49 @@ mod shared_enums;
use std::{
io::{BufReader, Write},
net::TcpListener,
+ time::Duration,
};
use crate::{
+ request::ServerPath,
response::{Response, ResponseCode, ResponseHeader},
- shared_enums::Content,
+ shared_enums::{Content, ContentType},
};
fn main() -> std::io::Result<()> {
let listener = TcpListener::bind("127.0.0.1:8080")?;
for incoming_stream in listener.incoming() {
- let stream = incoming_stream?;
+ let mut stream = incoming_stream?;
+ stream.set_read_timeout(Some(Duration::from_millis(500)))?;
- let reader = BufReader::new(&stream);
+ loop {
+ let reader = BufReader::new(&stream);
+ let req = match request::Request::from_bufreader(reader) {
+ Ok(r) => r,
+ Err(_) => break,
+ };
- let req = request::Request::from_bufreader(reader)?;
+ println!("{req:?}");
- println!("{req:?}");
+ let response = match req.path.path.to_string().as_str(){
+ "css.css" => Response::new().with_code(ResponseCode::Ok).with_data(b"body{background-color: #000000;}".to_vec()).with_header(ResponseHeader::ContentType(Content::new(ContentType::Text(shared_enums::TextType::Css)))),
- let mut writer = stream;
-
- let response = Response::new()
+ _ => Response::new()
.with_code(ResponseCode::Ok)
- .with_data(b"
Hello World!Ahojky
Jou jou jou
".to_vec())
- .with_header(ResponseHeader::ContentType(Content::html_utf8()));
+ .with_data(b"Hello World!Ahojky
Jou jou jou
".to_vec())
+ .with_header(ResponseHeader::ContentType(Content::html_utf8())),
+ };
- response.respond(&mut writer)?;
+ response.respond(&mut stream)?;
- writer.flush()?;
+ stream.flush()?;
+
+ if req.headers.contains(&request::RequestHeader::Connection(
+ request::Connection::Close,
+ )) {
+ break;
+ }
+ }
}
Ok(())
}
diff --git a/src/request.rs b/src/request.rs
index a7cb462..43bcabb 100644
--- a/src/request.rs
+++ b/src/request.rs
@@ -19,13 +19,42 @@ pub struct Request {
pub body: Option>,
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub enum RequestHeader {
Host(String),
UserAgent(String),
ContentType(Content),
Accept(Vec),
- Other(Box, Box),
+ Connection(Connection),
+ Upgrade(Vec),
+ Other { name: Box, value: Box },
+}
+
+#[derive(Debug, PartialEq)]
+pub enum Connection {
+ Close,
+ KeepAlive,
+ Upgrade,
+ Other(Box),
+}
+
+#[derive(Debug, PartialEq)]
+pub struct Upgrade {
+ protocol: Protocol,
+ version: Box,
+}
+
+impl FromStr for Upgrade {
+ type Err = io::Error;
+ fn from_str(s: &str) -> Result {
+ todo!()
+ }
+}
+
+#[derive(Debug, PartialEq)]
+pub enum Protocol {
+ HTTP,
+ Websocket,
}
impl FromStr for RequestHeader {
@@ -45,10 +74,22 @@ impl FromStr for RequestHeader {
.map(Content::from_str)
.collect::, io::Error>>()?,
)),
- _ => Ok(RequestHeader::Other(
- header_type.to_string().into_boxed_str(),
- value.to_string().into_boxed_str(),
+ "Connection" => Ok(RequestHeader::Connection(match *value {
+ "close" => Connection::Close,
+ "keep-alive" => Connection::KeepAlive,
+ "Upgrade" => Connection::Upgrade,
+ other => Connection::Other(other.to_string().into_boxed_str()),
+ })),
+ "Upgrade" => Ok(RequestHeader::Upgrade(
+ value
+ .split(',')
+ .map(Upgrade::from_str)
+ .collect::, io::Error>>()?,
)),
+ _ => Ok(RequestHeader::Other {
+ name: header_type.to_string().into_boxed_str(),
+ value: value.to_string().into_boxed_str(),
+ }),
},
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
@@ -81,7 +122,7 @@ impl Request {
let header = RequestHeader::from_str(¤t_line)?;
headers.push(header);
- if let RequestHeader::Other(_, _) = headers.last().unwrap() {
+ if let RequestHeader::Other { .. } = headers.last().unwrap() {
continue;
}
diff --git a/src/shared_enums.rs b/src/shared_enums.rs
index 78ca4ea..aa58948 100644
--- a/src/shared_enums.rs
+++ b/src/shared_enums.rs
@@ -1,6 +1,6 @@
use std::{io, str::FromStr};
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub enum ContentType {
Text(TextType),
Aplication(ApplicationType),
@@ -21,7 +21,7 @@ impl ContentType {
}
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub enum Parameter {
Preference(f32),
Charset(Charset),
@@ -38,7 +38,7 @@ impl Parameter {
}
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub enum Charset {
UTF8,
}
@@ -51,7 +51,7 @@ impl Charset {
}
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub struct Content {
pub content_type: ContentType,
pub parameter: Option>,
@@ -232,6 +232,7 @@ impl FromStr for ContentType {
["application", "*"] => Ok(ContentType::Aplication(ApplicationType::Any)),
["image", "png"] => Ok(ContentType::Image(Image::Png)),
+ ["image", "apng"] => Ok(ContentType::Image(Image::Png)),
["image", "jpeg"] | ["image", "jpg"] => Ok(ContentType::Image(Image::Jpeg)),
["image", "avif"] => Ok(ContentType::Image(Image::Avif)),
["image", "webp"] => Ok(ContentType::Image(Image::Webp)),
@@ -246,7 +247,7 @@ impl FromStr for ContentType {
}
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub enum Image {
Png,
Avif,
@@ -269,7 +270,7 @@ impl Image {
}
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub enum TextType {
Html,
Css,
@@ -288,7 +289,7 @@ impl TextType {
}
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub enum ApplicationType {
Json,
Any,