Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/alshdavid/uhttp
Rust HTTP Server Library for Humans
https://github.com/alshdavid/uhttp
Last synced: 26 days ago
JSON representation
Rust HTTP Server Library for Humans
- Host: GitHub
- URL: https://github.com/alshdavid/uhttp
- Owner: alshdavid
- Created: 2024-06-30T23:03:00.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2024-09-01T23:15:29.000Z (4 months ago)
- Last Synced: 2024-11-24T19:19:14.517Z (about 1 month ago)
- Language: HTML
- Homepage:
- Size: 862 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ยตHTTP ๐ฆ๐๐
A fast, tiny library for writing HTTP servers in Rust designed for humans:
- **Simple:** Inspired by Go's standard library HTTP server.
- **Fast:** High performance, multi-threaded implementation built on top of Tokio that competes with the fastest Rust HTTP servers.
- **Flexible**: Simple interface that enables many use cases. It can be used directly or to act as a base for frameworks to build on top of.
## Installation
Available on [crates.io](https://crates.io/crates/uhttp), install with:
```shell
cargo add uhttp
```## Benchmarks
Running on my desktop PC with a 7950x
```
oha -n 500000 -c 500 --latency-correction http://localhost:8080
``````mermaid
---
config:
xyChart:
showTick: true
---
xychart-beta
title "Requests Per Second"
x-axis ["hyper", "uhttp", "Go HTTP", "Node.js (uws library)", "Node.js (std)"]
y-axis "Requests Per Second" 0 --> 500000
bar [497432, 493671, 412250, 140929, 79966]
```# Usage
## Get Request
```rust
use std::io;use uhttp::http1::Server;
use uhttp::HttpWriter;
use uhttp::Request;
use uhttp::Response;#[tokio::main]
async fn main() -> io::Result<()> {
Server::new(handler).listen("0.0.0.0:8080").await
}async fn handler(mut _req: Request, mut res: Response) -> io::Result<()> {
res.write_all(b"Hello World!").await?;
res.write_header(200).await
}
```## Request Body
```rust
use std::io;use uhttp::http1::Server;
use uhttp::Request;
use uhttp::Response;#[tokio::main]
async fn main() -> io::Result<()> {
Server::new(handler).listen("0.0.0.0:8080").await
}async fn handler(mut req: Request, mut res: Response) -> io::Result<()> {
let body_text = uhttp::utils::body::utf8(&mut req).await?;
println!("{}", body_text);res.write_header(201).await
}
```## Routing
The URL is passed into the handler as a `String` and can be used to match request paths to routes. You can use simple if statements or a third party URL matching library to handle routing.
_TODO: Adding a basic router_
```rust
use std::io;use uhttp::http1::Server;
use uhttp::HttpWriter;
use uhttp::Request;
use uhttp::Response;#[tokio::main]
async fn main() -> io::Result<()> {
Server::new(handler).listen("0.0.0.0:8080").await
}async fn handler(mut req: Request, mut res: Response) -> io::Result<()> {
if req.method == "GET" && req.url == "/" {
return res.write_all(b"Hello World!").await
}if req.method == "POST" && req.url == "/api/echo" {
let bytes = uhttp::utils::body::bytes(&mut req).await?;
return res.write_all(&bytes).await
}res.write_header(404).await
}
```## Serving a File
```rust
use std::io;
use std::path::PathBuf;use tokio::fs;
use uhttp::http1::Server;
use uhttp::HttpWriter;
use uhttp::Request;
use uhttp::Response;const CARGO_HOME: &str = env!("CARGO_MANIFEST_DIR");
#[tokio::main]
async fn main() -> io::Result<()> {
Server::new(handler).listen("0.0.0.0:8080").await
}async fn handler(_req: Request, mut res: Response) -> io::Result<()> {
let index_file = PathBuf::from(CARGO_HOME).join("index.html");
let bytes = fs::read(&index_file).await?;
res.write_all(&bytes).await?;
res.write_header(200).await
}
```## Constants
Provided are some constants to make responses more consistent
```rust
use std::io;
use std::io::Write;use uhttp::http1::Server;
use uhttp::Request;
use uhttp::Response;
use uhttp::c;fn main() -> io::Result<()> {
Server::new(handler).listen("0.0.0.0:8080")
}fn handler(req: Request, mut res: Response) -> io::Result<()> {
res.headers().set(c::headers::CONTENT_TYPE, c::content_type::TEXT_PLAIN);
res.write_all(b"Hello World!")
res.write_header(c::status::OK)
}
```# Performance
## Setting Headers Explicitly
Setting the `Content-Type`, `Content-Length` or `Transfer-Encoding` explicitly will improve performance as the server does not need to detect them automatically.
### TODO
- Provide compressor utils for `Content-Encoding`: `gzip` and `br`
- `Transfer-Encoding: chunked`
- [Server Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) (use this instead of WebSocket)
- HTTP/2
- More performance improvements### Out of Scope
Though feel free to raise a PR to add support
- WebSocket