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
18 changes: 11 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
[package]
edition = "2024"
name = "hteapot"
version = "0.5.0"
exclude = ["config.toml", "demo/", "readme.md"]
license = "MIT"
keywords = ["HTTP", "HTTP-SERVER"]
edition = "2024"
authors = ["Alb Ruiz G. <me@albruiz.dev>"]
description = "HTeaPot is a lightweight HTTP server library designed to be easy to use and extend."
license = "MIT"
readme = "README.md"
documentation = "https://docs.rs/hteapot/"
homepage = "https://github.com/az107/HTeaPot"
repository = "https://github.com/az107/HTeaPot"
readme = "readme.md"
categories = ["network-programming", "web-programming"]
authors = ["Alb Ruiz G. <me@albruiz.dev>"]
keywords = ["http", "server", "web", "lightweight", "rust"]
categories = ["network-programming", "web-programming", "command-line-utilities"]
exclude = ["config.toml", "demo/", "README.md"]

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

[[bin]]
name = "hteapot"

[package.metadata.docs.rs]
no-readme = true
62 changes: 43 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,19 @@

A high-performance, lightweight HTTP server and library built in Rust. HTeaPot is designed to deliver exceptional performance for modern web applications while maintaining a simple and intuitive API.

## Features
## 📚 Table of Contents

- [Features](#--features)
- [Getting Started](#-getting-started)
- [Standalone Server](#standalone-server)
- [As a Library](#as-a-library)
- [Performance](#-performance)
- [Roadmap](#-roadmap)
- [Contributing](#-contributing)
- [License](#-license)
- [Acknowledgments](#-acknowledgments)

## ✨ Features

### Exceptional Performance
- **Threaded Architecture**: Powered by a custom-designed thread system that handles **70,000+ requests per second**
Expand All @@ -34,9 +46,9 @@ A high-performance, lightweight HTTP server and library built in Rust. HTeaPot i
- **Extensible Design**: Easily customize behavior for specific use cases
- **Lightweight Footprint**: Zero dependencies and efficient resource usage

## Getting Started
## 🚀 Getting Started

### Installation
### 🔧 Installation

```bash
# Install from crates.io
Expand All @@ -48,11 +60,11 @@ cd hteapot
cargo build --release
```

### Standalone Server
### 🖥️ Running the Server

#### Using a configuration file:
#### Option 1: With Config

Create a `config.toml` file:
1. Create a `config.toml` file:

```toml
[HTEAPOT]
Expand All @@ -61,27 +73,27 @@ host = "localhost" # The host address to bind to
root = "public" # The root directory to serve files from
```

Run the server:
2. Run the server:

```bash
hteapot ./config.toml
```

#### Quick serve a directory:
#### Option 2: Quick Serve

```bash
hteapot -s ./public/
```

### As a Library
### 🦀 Using as a Library

1. Add HTeaPot to your project:
1. Add HTeaPot to your ```Cargo.toml``` project:

```bash
cargo add hteapot
```

2. Implement in your code:
2. Implement in your code: ```example```

```rust
use hteapot::{HttpStatus, HttpResponse, Hteapot, HttpRequest};
Expand All @@ -97,16 +109,16 @@ fn main() {
}
```

## Performance
## 📊 Performance

HTeaPot has been benchmarked against other popular HTTP servers, consistently demonstrating excellent metrics:

| Metric | HTeaPot | Industry Average |
|---------------|---------|------------------|
| Requests/sec | 70,000+ | 30,000-50,000 |
| Error rate | <0.1% | 0.5-2% |
| Latency (p99) | 5ms | 15-30ms |
| Memory usage | Low | Moderate |
| Metric | HTeaPot | Industry Average |
|---------------|---------------|------------------------|
| Requests/sec | 70,000+ req/s | 30,000 - 50,000 req/s |
| Error rate | < 0.1% | 0.5% - 2% |
| Latency (p99) | 5ms | 15ms - 30ms |
| Memory usage | Low | Moderate |

## Roadmap

Expand All @@ -122,7 +134,19 @@ HTeaPot has been benchmarked against other popular HTTP servers, consistently de

## Contributing

We welcome contributions from the community! See our [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to get involved.
We welcome contributions from the community! To get started:

```sh
# Format the code
cargo fmt

# Lint for warnings
cargo clippy --all-targets --all-features

# Run tests
cargo test
```
See [CONTRIBUTING.md](https://github.com/Az107/HTeaPot/wiki/Contributing) for more details.

## License

Expand Down
39 changes: 38 additions & 1 deletion src/cache.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
// 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;

/// A simple in-memory cache with TTL (time-to-live) support.
///
/// This cache stores byte arrays (`Vec<u8>`) along with an expiration timestamp.
/// When a cached entry is fetched, the TTL is validated. If it's expired, the
/// item is removed and `None` is returned.
///
/// Note: Currently not generic, but could be extended in the future to support
/// other data types.
///
/// # Example
/// ```
/// let mut cache = Cache::new(60); // 60 seconds TTL
/// cache.set("hello".into(), vec![1, 2, 3]);
/// let data = cache.get("hello".into());
/// assert!(data.is_some());
/// ```
pub struct Cache {
//TODO: consider make it generic
// TODO: consider make it generic
// The internal store: (data, expiration timestamp)
data: HashMap<String, (Vec<u8>, u64)>,
max_ttl: u64,
}

impl Cache {
/// Creates a new `Cache` with the specified TTL in seconds.
pub fn new(max_ttl: u64) -> Self {
Cache {
data: HashMap::new(),
max_ttl,
}
}

/// Creates a new `Cache` with the specified TTL in seconds.
fn validate_ttl(&self, ttl: u64) -> bool {
let now = SystemTime::now();
let since_epoch = now
Expand All @@ -29,6 +50,7 @@ impl Cache {
secs < ttl
}

/// Computes the expiration timestamp for a new cache entry.
fn get_ttl(&self) -> u64 {
let now = SystemTime::now();
let since_epoch = now
Expand All @@ -38,10 +60,14 @@ impl Cache {
secs + self.max_ttl
}

/// Stores data in the cache with the given key and a TTL.
pub fn set(&mut self, key: String, data: Vec<u8>) {
self.data.insert(key, (data, self.get_ttl()));
}

/// Retrieves data from the cache if it exists and hasn't expired.
///
/// Removes and returns `None` if the TTL has expired.
pub fn get(&mut self, key: String) -> Option<Vec<u8>> {
let r = self.data.get(&key);
if r.is_some() {
Expand All @@ -55,5 +81,16 @@ impl Cache {
} else {
None
}

// Alternative implementation using pattern matching
// This is a more idiomatic way to handle the Option type in Rust.
// match self.data.get(&key) {
// Some((data, ttl)) if self.validate_ttl(*ttl) => Some(data.clone()),
// Some(_) => {
// self.data.remove(&key);
// None
// }
// None => None,
// }
}
}
Loading