khttp (Karl's HTTP)
khttp is a low-level, synchronous HTTP/1.1 micro-framework for Rust - written from scratch with a focus on:
- Keeping things simple
- Low memory footprint
- Low overhead / high performance
- Minimal dependencies (
libc, memchr)
Features:
- HTTP/1.1 server & optional client (
--features client)
- Zero-copy(-ish) parsing with SIMD
- Router with params & wildcards:
/user/:id, /static/**
- Automatic framing:
Content-Length & Transfer-Encoding: chunked
- Automatic
date header
- Custom epoll event loop on Linux (
--features epoll)
use khttp::{Headers, Method::*, PreRoutingAction, Server, Status};
fn main() {
let mut app = Server::builder("127.0.0.1:8080").unwrap();
app.route(Get, "/", |ctx, res| {
println!(
"Received request.\nmethod: {}\nquery: {}\nheaders:\n{}",
ctx.method,
ctx.uri.query().unwrap_or(""),
ctx.headers
);
let mut headers = Headers::new();
headers.add("key", b"value");
headers.add(String::from("owned"), b"value".to_vec());
res.ok(&headers, &b"Hello, World!"[..])
});
app.route(Post, "/uppercase", |mut ctx, res| {
let body = ctx.body().string().unwrap_or_default();
let response_body = body.to_ascii_uppercase();
res.ok(Headers::empty(), response_body.as_bytes())
});
app.route(Get, "/user/:id", |c, r| {
let user_id: u64 = match c.params.get("id").unwrap().parse() {
Ok(id) => id,
Err(_) => {
return r.send(&Status::BAD_REQUEST, Headers::empty(), &b"bad id"[..]);
}
};
r.ok(Headers::empty(), format!("{}", user_id).as_bytes())
});
app.fallback_route(|_, r| r.send(&Status::NOT_FOUND, Headers::empty(), &b"404"[..]));
app.thread_count(20);
app.max_request_head_size(16 * 1024);
app.pre_routing_hook(|req, res, conn| {
if conn.index() > 100 {
let _ = res.send(&Status::of(429), Headers::close(), std::io::empty());
return PreRoutingAction::Drop;
}
if req.http_version == 0 {
let _ = res.send(&Status::of(505), Headers::close(), std::io::empty());
return PreRoutingAction::Drop;
}
if matches!(req.method, Custom(_)) {
let _ = res.send(&Status::of(405), Headers::close(), std::io::empty());
return PreRoutingAction::Drop;
}
PreRoutingAction::Proceed
});
app.build().serve_epoll().unwrap();
}
See other examples for:
License
MIT.