diff --git a/Cargo.lock b/Cargo.lock index 1d592af..88a6e23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "aho-corasick" version = "1.1.5" @@ -61,12 +76,66 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "color-eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + [[package]] name = "colorchoice" version = "1.0.5" @@ -127,14 +196,39 @@ dependencies = [ "log", ] +[[package]] +name = "eyre" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08309dbcc659c5549a24ddb9b27027640641b282ef5768267c7e675558986a3" +dependencies = [ + "autocfg", + "indenter", + "once_cell", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + [[package]] name = "http_server" version = "0.1.0" dependencies = [ + "color-eyre", "env_logger", "log", + "thiserror", ] +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -177,6 +271,18 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + [[package]] name = "log" version = "0.4.33" @@ -189,12 +295,48 @@ version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + [[package]] name = "once_cell_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "portable-atomic" version = "1.15.0" @@ -257,6 +399,12 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +[[package]] +name = "rustc-demangle" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" + [[package]] name = "serde_core" version = "1.0.229" @@ -277,6 +425,15 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "syn" version = "2.0.119" @@ -319,6 +476,56 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + [[package]] name = "unicode-ident" version = "1.0.24" @@ -331,6 +538,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "windows-link" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index adb6349..efec7bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,10 @@ version = "0.1.0" edition = "2024" [dependencies] +color-eyre = "0.6.5" env_logger = "0.11.11" log = "0.4.33" +thiserror = "2.0.20" [profile.dev] opt-level = 0 diff --git a/src/lib.rs b/src/lib.rs index 6377d31..1bf6ea7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,14 +2,16 @@ mod request; mod response; use request::{Header, ReqLine}; -use response::{Status, Version}; +use response::{Response, Version, Status}; use std::io::{BufReader, BufWriter, Read, Write}; use std::net::TcpStream; +use std::fs::File; +use std::path::{Path, PathBuf}; use log::{debug, info}; -pub fn handle_connection(conn: TcpStream) -> std::io::Result<()> { +pub fn handle_connection(conn: TcpStream) -> color_eyre::Result<()> { info!("Reveiced new connection from {}", conn.peer_addr()?); let reader = BufReader::new(conn.try_clone()?); @@ -47,10 +49,20 @@ pub fn handle_connection(conn: TcpStream) -> std::io::Result<()> { debug!("{}: {}", line.key, line.value); } - let resp = "HTTP/1.1 200 OK\r\n\r\nHello, world!\r\n"; + let file_path: Option = req_line.route.starts_with("/").then(|| { + req_line.route.split("/").map(|s| Path::new(a)).collect() + }); - let count = writer.write(resp.as_bytes())?; - info!("Response sent ({})", count); + let file_path = file_path.map(|p_buf| p_buf.canonicalize()); + + let file = file_path.map(|f_path| { + f_path.map(|f_path| File::open(f_path)) + }); + + let count: Result = resp.as_str_list().into_iter() + .map(|s| writer.write(s.as_bytes())) + .sum(); + info!("Response sent ({})", count?); writer.flush()?; diff --git a/src/response.rs b/src/response.rs index 4032fed..9adbe20 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,9 +1,79 @@ +#[derive(Debug, Default)] pub(crate) enum Version { + #[default] V11, } +#[derive(Debug, Default)] pub(crate) enum Status { + #[default] OK, NotFound, Forbidden, + BadRequest, +} + +trait AsStaticStr { + fn as_str(&self) -> &'static str; +} + +impl AsStaticStr for Version { + fn as_str(&self) -> &'static str { + match self { + Self::V11 => "HTTP/1.1", + } + } +} + +impl AsStaticStr for Status { + fn as_str(&self) -> &'static str { + match self { + Self::OK => "200 OK", + Self::NotFound => "404 Not Found", + Self::Forbidden => "403 Forbidden", + Self::BadRequest => "400 Bad Request", + } + } +} + +#[derive(Debug, Default)] +pub(crate) struct Header { + pub(crate) key: String, + pub(crate) value: String, +} + +impl Header { + pub(crate) fn as_str(&self) -> (&str, &str) { + (self.key.as_str(), self.value.as_str()) + } +} + +#[derive(Debug, Default)] +pub(crate) struct Response { + pub(crate) version: Version, + pub(crate) status: Status, + pub(crate) headers: Vec
, +} + +impl Response { + pub(crate) fn as_str_list(&self) -> Vec<&str> { + let mut ret = vec!( + self.version.as_str(), + " ", + self.status.as_str(), + "\r\n", + ); + ret.reserve(self.headers.len() * 3 + 5); + self.headers.iter() + .map(|header| header.as_str()) + .map(|(k, v)| (k, ": ", v)) + .for_each(|(x, y, z)| { + ret.push(x); + ret.push(y); + ret.push(z); + ret.push("\r\n"); + }); + ret.push("\r\n"); + ret + } } diff --git a/static/index.html b/static/index.html new file mode 100644 index 0000000..9a93579 --- /dev/null +++ b/static/index.html @@ -0,0 +1,49 @@ + + + + Test Page + + + +
+

Welcome to rust-http-server!

+
+
+

The basic function of this server is working properly, if you are able to see this page.

+
+ + +