Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 3 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
[package]
name = "hteapot"
version = "0.2.6"
exclude = [
"hteapot.toml",
"public/",
"readme.md"
]
version = "0.3.0"
exclude = ["hteapot.toml", "public/", "readme.md"]
license = "MIT"
keywords = ["HTTP", "HTTP-SERVER"]
description = "HTeaPot is a lightweight HTTP server library designed to be easy to use and extend."
Expand All @@ -17,9 +13,7 @@ authors = ["Alb Ruiz G. <me@albruiz.dev>"]

[lib]
name = "hteapot"
path = "src/hteapot.rs"
path = "src/hteapot/mod.rs"

[[bin]]
name = "hteapot"


5 changes: 3 additions & 2 deletions config.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
[HTEAPOT]
port = 8081
host = "0.0.0.0"
threads = 4
root = "public"
threads = 5
cache = true
cache_ttl = 3600
cache_ttl = 36
[proxy]
"/test" = "http://example.com"
"/google" = "http://google.com"
"/myip" = "http://ifconfig.co"
# "/" = "http://ifconfig.co" # this will override all the proxys and local request
28 changes: 25 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

[Spanish](docs/readme-es.md) | English

HteaPot is a simple HTTP server written in Rust. It allows you to serve static files and handle basic HTTP requests.
HteaPot is a simple HTTP server written in Rust. It allows you to serve static files and handle
HTTP requests.
It´s also a library to write http applictions like an api

# Features

Expand Down Expand Up @@ -33,13 +35,33 @@ You can configure the server using a TOML file. Here's an example configuration:
```toml
[HTEAPOT]
port = 8081 # The port on which the server will listen for incoming connections.
host = "localhost" # The host address to bind the server to.
host = "localhost" # The host address to bind the server to.
root = "public" # The root directory from which to serve files.
```

# Library use

For use hteapot as a library in rust
1. Install the library
```bash
$ cargo add hteapot
```

2. Then you can use it in your project
```Rust
use hteapot::{HttpStatus, Hteapot};

fn main() {
let server = Hteapot::new("localhost", 8081);
teapot.listen(move|req| {
}
```


# Contributing

Contributions are welcome! Feel free to open issues or submit pull requests.

# License

This project is licensed under the MIT License - see the LICENSE file for details.
This project is licensed under the MIT License - see the LICENSE file for details.
21 changes: 12 additions & 9 deletions src/brew.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
net::TcpStream,
};

#[derive(Debug)]
struct Url {
scheme: String,
domain: String,
Expand All @@ -27,7 +28,11 @@ fn parse_url(url: &str) -> Result<Url, &str> {
_ => "80",
}
};
let (domain, path) = domain_path.split_once('/').unwrap();
let (domain, path) = match domain_path.split_once('/') {
Some((a, b)) => (a, b),
None => (domain_path, ""),
};

Ok(Url {
scheme: prefix.to_string(),
domain: domain.to_string(),
Expand All @@ -51,21 +56,19 @@ pub fn fetch(url: &str) -> Result<Vec<u8>, &str> {
return Err("Error fetching");
}
let mut client = client.unwrap();
let http_request = format!("GET /{} HTTP/1.1\r\nHost: {}\r\n\r\n", url.path, url.domain);
let http_request = format!(
"GET /{} HTTP/1.1\nHost: {}\nConnection: Close\n\n",
url.path, url.domain
);
client.write(http_request.as_bytes()).unwrap();
let _ = client.flush();
let mut full_buffer: Vec<u8> = Vec::new();
let mut buffer = [0; 1024];
loop {
match client.read(&mut buffer) {
Ok(0) => break,
Ok(n) => {
if n == 0 {
break;
}
Ok(_n) => {
full_buffer.extend(buffer.iter().cloned());
if buffer.last().unwrap() == &0 {
break;
}
}
Err(_) => break,
}
Expand Down
59 changes: 59 additions & 0 deletions src/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Written by Alberto Ruiz, 2024-11-05
// Config module: handles application configuration setup and parsing.
// This module defines structs and functions to load and validate
// configuration settings from files, environment variables, or other sources.
use std::collections::HashMap;
use std::time;
use std::time::SystemTime;

pub struct Cache {
//TODO: consider make it generic
data: HashMap<String, (Vec<u8>, u64)>,
max_ttl: u64,
}

impl Cache {
pub fn new(max_ttl: u64) -> Self {
Cache {
data: HashMap::new(),
max_ttl,
}
}

fn validate_ttl(&self, ttl: u64) -> bool {
let now = SystemTime::now();
let since_epoch = now
.duration_since(time::UNIX_EPOCH)
.expect("Time went backwards");
let secs = since_epoch.as_secs();
secs < ttl
}

fn get_ttl(&self) -> u64 {
let now = SystemTime::now();
let since_epoch = now
.duration_since(time::UNIX_EPOCH)
.expect("Time went backwards");
let secs = since_epoch.as_secs();
secs + self.max_ttl
}

pub fn set(&mut self, key: String, data: Vec<u8>) {
self.data.insert(key, (data, self.get_ttl()));
}

pub fn get(&mut self, key: String) -> Option<Vec<u8>> {
let r = self.data.get(&key);
if r.is_some() {
let (data, ttl) = r.unwrap();
if self.validate_ttl(*ttl) {
Some(data.clone())
} else {
self.data.remove(&key);
None
}
} else {
None
}
}
}
3 changes: 2 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,13 @@ pub fn toml_parser(content: &str) -> HashMap<String, TOMLSchema> {
map
}

#[derive(Debug)]
pub struct Config {
pub port: u16, // Port number to listen
pub host: String, // Host name or IP
pub root: String, // Root directory to serve files
pub cache: bool,
pub cache_ttl: u64,
pub cache_ttl: u16,
pub threads: u16,
pub index: String, // Index file to serve by default
//pub error: String, // Error file to serve when a file is not found
Expand Down
50 changes: 50 additions & 0 deletions src/hteapot/methods.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum HttpMethod {
GET,
POST,
PUT,
DELETE,
PATCH,
HEAD,
OPTIONS,
TRACE,
CONNECT,
Other(String),
}

impl HttpMethod {
pub fn from_str(method: &str) -> HttpMethod {
match method {
"GET" => HttpMethod::GET,
"POST" => HttpMethod::POST,
"PUT" => HttpMethod::PUT,
"DELETE" => HttpMethod::DELETE,
"PATCH" => HttpMethod::PATCH,
"HEAD" => HttpMethod::HEAD,
"OPTIONS" => HttpMethod::OPTIONS,
"TRACE" => HttpMethod::TRACE,
"CONNECT" => HttpMethod::CONNECT,
_ => Self::Other(method.to_string()),
}
}
pub fn to_str(&self) -> &str {
match self {
HttpMethod::GET => "GET",
HttpMethod::POST => "POST",
HttpMethod::PUT => "PUT",
HttpMethod::DELETE => "DELETE",
HttpMethod::PATCH => "PATCH",
HttpMethod::HEAD => "HEAD",
HttpMethod::OPTIONS => "OPTIONS",
HttpMethod::TRACE => "TRACE",
HttpMethod::CONNECT => "CONNECT",
HttpMethod::Other(method) => method.as_str(),
}
}
}

// #[derive(Clone, Copy)]
// pub enum Protocol {
// HTTP,
// HTTPS,
// }
Loading