-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ce350a7
Showing
20 changed files
with
969 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[target.x86_64-pc-windows-msvc] | ||
rustflags = ["-Ctarget-feature=+crt-static"] | ||
|
||
[target.i686-pc-windows-msvc] | ||
rustflags = ["-Ctarget-feature=+crt-static"] | ||
|
||
[target.i586-pc-windows-msvc] | ||
rustflags = ["-Ctarget-feature=+crt-static"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/target | ||
*.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[package] | ||
edition = "2021" | ||
name = "rusty_httpd" | ||
version = "0.1.0" | ||
|
||
[dependencies] | ||
case_insensitive_hashmap = "1.0.0" | ||
const_format = "0.2.30" | ||
crossbeam-channel = "0.5.6" | ||
ctrlc = "3.2.4" | ||
lazy_static = "1.4.0" | ||
log = "0.4.17" | ||
env_logger = "0.10.0" | ||
mtcp-rs = "0.1.8" | ||
num_cpus = "1.15.0" | ||
rand = "0.8.5" | ||
regex = "1.7.1" | ||
urlencoding = "2.1.2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/bash | ||
find . -name '*.rs' -printf "%d %P\n" | sort -n | cut -c3- | xargs -i bash -c \ | ||
'printf "\n\n/* -------------------------------- */\n/* %-32s */\n/* -------------------------------- */\n\n" "{}"; cat "{}"' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="utf-8"> | ||
<title>Cool Title</title> | ||
<link rel="stylesheet" href="style.css"> | ||
</head> | ||
|
||
<body> | ||
<h1>Welcome from index.html</h1> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
h1 { | ||
color: red | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use std::{fmt::Display, path::Path}; | ||
use case_insensitive_hashmap::CaseInsensitiveHashMap; | ||
|
||
use lazy_static::lazy_static; | ||
|
||
#[derive(Copy, Clone)] | ||
pub enum ContentType { | ||
Binary, | ||
BZip2, | ||
CSS, | ||
GIF, | ||
GZip, | ||
HTML, | ||
JavaScript, | ||
JPEG, | ||
PDF, | ||
PNG, | ||
Tar, | ||
Text, | ||
ZIP, | ||
XZ, | ||
} | ||
|
||
lazy_static! { | ||
static ref EXTENSIONS: CaseInsensitiveHashMap<ContentType> = { | ||
let mut builder = CaseInsensitiveHashMap::new(); | ||
builder.insert("bin", ContentType::Binary); | ||
builder.insert("bz2", ContentType::BZip2); | ||
builder.insert("css", ContentType::CSS); | ||
builder.insert("dat", ContentType::Binary); | ||
builder.insert("exe", ContentType::Binary); | ||
builder.insert("gif", ContentType::GIF); | ||
builder.insert("gz", ContentType::GZip); | ||
builder.insert("htm", ContentType::HTML); | ||
builder.insert("html", ContentType::HTML); | ||
builder.insert("jpe", ContentType::JPEG); | ||
builder.insert("jpeg", ContentType::JPEG); | ||
builder.insert("jpg", ContentType::JPEG); | ||
builder.insert("js", ContentType::JavaScript); | ||
builder.insert("pdf", ContentType::PDF); | ||
builder.insert("png", ContentType::PNG); | ||
builder.insert("tar", ContentType::Tar); | ||
builder.insert("tbz2", ContentType::BZip2); | ||
builder.insert("tgz", ContentType::GZip); | ||
builder.insert("txt", ContentType::Text); | ||
builder.insert("txz", ContentType::XZ); | ||
builder.insert("xz", ContentType::XZ); | ||
builder.insert("zip", ContentType::ZIP); | ||
builder | ||
}; | ||
} | ||
|
||
impl ContentType { | ||
pub fn from_path(path: &Path) -> Option<ContentType> { | ||
match path.extension() { | ||
Some(ext) => match ext.to_str() { | ||
Some(str) => EXTENSIONS.get(str).copied(), | ||
None => None, | ||
}, | ||
None => None, | ||
} | ||
} | ||
|
||
pub fn as_str(&self) -> &'static str { | ||
match *self { | ||
Self::Binary => "application/octet-stream", | ||
Self::CSS => "text/css", | ||
Self::GIF => "image/gif", | ||
Self::GZip => "application/gzip", | ||
Self::BZip2 => "application/x-bzip2", | ||
Self::HTML => "text/html", | ||
Self::JavaScript => "text/javascript", | ||
Self::JPEG => "image/jpg", | ||
Self::PDF => "application/pdf", | ||
Self::PNG => "image/png", | ||
Self::Tar => "application/x-tar", | ||
Self::Text => "text/plain", | ||
Self::ZIP => "application/zip", | ||
Self::XZ => "application/x-xz", | ||
} | ||
} | ||
} | ||
|
||
impl AsRef<str> for ContentType { | ||
fn as_ref(&self) -> &str { | ||
self.as_str() | ||
} | ||
} | ||
|
||
impl Display for ContentType { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.as_ref()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use core::str::Lines; | ||
use std::convert::TryFrom; | ||
use std::io::{Error as IoError, ErrorKind}; | ||
use crate::utils::ValueMap; | ||
|
||
#[derive(Debug)] | ||
pub struct Headers<'buf> { | ||
map: ValueMap<'buf>, | ||
} | ||
|
||
impl<'buf> Headers<'buf> { | ||
pub fn names(&'buf self) -> impl Iterator<Item = &'buf str> { | ||
self.map.keys() | ||
} | ||
|
||
pub fn values(&'buf self, name: &str) -> Option<impl Iterator<Item = &str>> { | ||
self.map.values(name) | ||
} | ||
} | ||
|
||
impl<'buf> TryFrom<Lines<'buf>> for Headers<'buf> { | ||
type Error = IoError; | ||
|
||
fn try_from(lines: Lines<'buf>) -> Result<Self, IoError> { | ||
let mut map = ValueMap::new(); | ||
|
||
for line in lines.map(str::trim).take_while(|&str| !str.is_empty()) { | ||
let mut parts = line.splitn(2, ':'); | ||
let key = parts.next().map(str::trim).unwrap_or_default(); | ||
let val = parts.next().map(str::trim).unwrap_or_default(); | ||
|
||
if !key.is_empty() { | ||
map.put(key.into(), val.into()); | ||
} | ||
} | ||
|
||
if map.is_empty() { | ||
return Err(IoError::new(ErrorKind::NotFound, "No headers found!")); | ||
} | ||
|
||
Ok (Self { map }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use core::fmt; | ||
use std::{str::FromStr, fmt::Display}; | ||
|
||
#[derive(Debug)] | ||
pub enum Method { | ||
GET, | ||
DELETE, | ||
POST, | ||
PUT, | ||
HEAD, | ||
CONNECT, | ||
OPTIONS, | ||
TRACE, | ||
PATCH, | ||
} | ||
|
||
impl FromStr for Method { | ||
type Err = MethodError; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
let uppr = s.trim().to_ascii_uppercase(); | ||
match uppr.as_str() { | ||
"GET" => Ok(Self::GET), | ||
"DELETE" => Ok(Self::DELETE), | ||
"POST" => Ok(Self::POST), | ||
"PUT" => Ok(Self::PUT), | ||
"HEAD" => Ok(Self::HEAD), | ||
"CONNECT" => Ok(Self::CONNECT), | ||
"OPTIONS" => Ok(Self::OPTIONS), | ||
"TRACE" => Ok(Self::TRACE), | ||
"PATCH" => Ok(Self::PATCH), | ||
_ => Err(MethodError), | ||
} | ||
} | ||
} | ||
|
||
impl Display for Method { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
fmt::Debug::fmt(self, f) | ||
} | ||
} | ||
|
||
pub struct MethodError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
pub use method::Method; | ||
pub use query_string::QueryString; | ||
pub use headers::Headers; | ||
pub use request::ParseError; | ||
pub use request::Request; | ||
pub use response::Response; | ||
pub use status_code::StatusCode; | ||
|
||
pub mod method; | ||
pub mod query_string; | ||
pub mod headers; | ||
pub mod request; | ||
pub mod response; | ||
pub mod status_code; | ||
pub mod content_type; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
use std::borrow::Cow; | ||
use std::convert::TryFrom; | ||
use std::io::{Error as IoError, ErrorKind}; | ||
use crate::utils::ValueMap; | ||
use urlencoding::decode as url_decode; | ||
|
||
#[derive(Debug)] | ||
pub struct QueryString<'buf> { | ||
map: ValueMap<'buf>, | ||
} | ||
|
||
impl<'buf> QueryString<'buf>{ | ||
pub fn keys(&self) -> impl Iterator<Item = &str> { | ||
self.map.keys() | ||
} | ||
|
||
pub fn values(&self, key: &str) -> Option<impl Iterator<Item = &str>> { | ||
self.map.values(key) | ||
} | ||
} | ||
|
||
impl<'buf> TryFrom<&'buf str> for QueryString<'buf> { | ||
type Error = IoError; | ||
|
||
fn try_from(query_string: &'buf str) -> Result<Self, IoError> { | ||
let mut map = ValueMap::new(); | ||
|
||
for sub_str in query_string.split('&').map(str::trim).filter(|&str| !str.is_empty()) { | ||
let mut parts = sub_str.splitn(2, '='); | ||
let key = decode(parts.next().map(str::trim).unwrap_or_default()); | ||
let val = decode(parts.next().map(str::trim).unwrap_or_default()); | ||
|
||
if !key.is_empty() { | ||
map.put(key, val); | ||
} | ||
} | ||
|
||
if map.is_empty() { | ||
return Err(IoError::new(ErrorKind::NotFound, "No query parameters found!")); | ||
} | ||
|
||
Ok(Self { map }) | ||
} | ||
} | ||
|
||
fn decode(str: &str) -> Cow<str> { | ||
match url_decode(str) { | ||
Ok(decoded) => decoded, | ||
Err(_) => str.into() | ||
} | ||
} |
Oops, something went wrong.