Expand description
§Hyperlite
Hyperlite is a lightweight HTTP framework built on top of hyper, tokio, and
tower for building fast, composable web services without sacrificing control.
§Philosophy
- Stay close to
hyperprimitives for maximum flexibility. - Embrace Tower’s
Servicetrait for middleware-first composition. - Provide type-safe request and response helpers without macros.
- Favor zero-cost abstractions over hidden magic.
§Key Features
- Fast path-based routing powered by
matchit. - Tower middleware compatibility, including tracing, CORS, and authentication layers.
- Ergonomic response builders and JSON helpers.
- Built-in server runner with graceful shutdown handling.
- Focus on predictable upgrades by avoiding breaking framework changes.
- ✅ Type-safe request extraction helpers for bodies, queries, paths, and extensions.
§Quick Example
use bytes::Bytes;
use hyper::{Method, Request, Response, StatusCode};
use hyperlite::{serve, success, BoxBody, Router};
use http_body_util::Full;
use serde::Serialize;
use std::net::SocketAddr;
use std::sync::Arc;
#[derive(Clone)]
struct AppState;
#[derive(Serialize)]
struct Greeting {
message: String,
}
async fn hello_handler(
_req: Request<BoxBody>,
_state: Arc<AppState>,
) -> Result<Response<Full<Bytes>>, hyperlite::BoxError> {
Ok(success(
StatusCode::OK,
Greeting {
message: "Hello, World!".to_string(),
},
))
}
#[tokio::main]
async fn main() -> Result<(), hyperlite::BoxError> {
let state = AppState;
let router = Router::new(state).route(
"/hello",
Method::GET,
Arc::new(|req, state| Box::pin(hello_handler(req, state))),
);
let addr: SocketAddr = "127.0.0.1:3000".parse().unwrap();
serve(addr, router).await
}For richer walkthroughs, inspect the examples/ directory:
hello_world.rs– Minimal single-route server.with_state.rs– Shared state with all extractors.with_middleware.rs– Complete Tower middleware stack.
Run any example via cargo run --example <name>.
§Request Extraction
use bytes::Bytes;
use hyper::{Method, Request, Response, StatusCode};
use hyperlite::{parse_json_body, path_param, query_params, BoxBody, BoxError, Router, success};
use http_body_util::Full;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use uuid::Uuid;
#[derive(Clone)]
struct AppState;
#[derive(Deserialize)]
struct CreatePost { title: String, body: String }
#[derive(Deserialize)]
struct Pagination { page: u32, limit: u32 }
#[derive(Serialize)]
struct Post { id: Uuid, title: String }
async fn create_post(
req: Request<BoxBody>,
_state: Arc<AppState>,
) -> Result<Response<Full<Bytes>>, BoxError> {
let payload = parse_json_body::<CreatePost>(req).await?;
Ok(success(StatusCode::CREATED, Post {
id: Uuid::new_v4(),
title: payload.title,
}))
}
async fn list_posts(
req: Request<BoxBody>,
_state: Arc<AppState>,
) -> Result<Response<Full<Bytes>>, BoxError> {
let params = query_params::<Pagination>(&req)?;
Ok(success(StatusCode::OK, format!("page={}", params.page)))
}
async fn get_post(
req: Request<BoxBody>,
_state: Arc<AppState>,
) -> Result<Response<Full<Bytes>>, BoxError> {
let post_id: Uuid = path_param(&req, "id")?;
Ok(success(StatusCode::OK, Post { id: post_id, title: "Example".into() }))
}
#[tokio::main]
let state = AppState;
let router = Router::new(state)
.route("/posts", Method::POST, Arc::new(|req, state| Box::pin(create_post(req, state))))
.route("/posts", Method::GET, Arc::new(|req, state| Box::pin(list_posts(req, state))))
.route("/posts/{id}", Method::GET, Arc::new(|req, state| Box::pin(get_post(req, state))));
let addr: std::net::SocketAddr = "127.0.0.1:3000".parse().unwrap();
hyperlite::serve(addr, router).await
}See examples/with_state.rs for a full application using these helpers in
tandem with shared state and realistic routing patterns.
§Examples
cargo run --example hello_world
cargo run --example with_state
RUST_LOG=info cargo run --example with_middlewareEach example demonstrates progressively more advanced patterns, from simple routing to full middleware stacks with distributed tracing.
§When To Use
Choose Hyperlite when you want the ergonomics of a framework while keeping full control over the underlying HTTP server and middleware stack.
Re-exports§
pub use extract::get_extension;pub use extract::parse_json_body;pub use extract::path_param;pub use extract::path_params;pub use extract::query_params;pub use response::empty;pub use response::failure;pub use response::not_found;pub use response::success;pub use response::with_correlation_id;pub use response::ApiError;pub use response::ResponseBody;pub use router::BodyError;pub use router::BoxBody;pub use router::Handler;pub use router::PathParams;pub use router::Router;pub use server::serve;
Modules§
- extract
- Request extraction helpers for Hyperlite services.
- response
- Response builders for consistent JSON API envelopes.
- router
- Usage with Server
- server
- Server utilities for running Hyperlite applications.