micro_http/lib.rs
1//! An asynchronous micro HTTP server implementation
2//!
3//! This crate provides a lightweight, efficient, and modular HTTP/1.1 server implementation
4//! built on top of tokio. It focuses on providing a clean API while maintaining high performance
5//! through careful memory management and asynchronous processing.
6//!
7//! # Features
8//!
9//! - Full HTTP/1.1 protocol support
10//! - Asynchronous I/O using tokio
11//! - Streaming request and response bodies
12//! - Chunked transfer encoding
13//! - Keep-alive connections
14//! - Expect-continue mechanism
15//! - Efficient memory usage through zero-copy parsing
16//! - Clean error handling
17//!
18//!
19//! # Example
20//!
21//! ```no_run
22//! use http::{Request, Response, StatusCode};
23//! use http_body_util::BodyExt;
24//! use std::error::Error;
25//! use std::sync::Arc;
26//! use tokio::net::TcpListener;
27//! use tracing::{error, info, warn, Level};
28//! use tracing_subscriber::FmtSubscriber;
29//! use micro_http::connection::HttpConnection;
30//! use micro_http::handler::make_handler;
31//! use micro_http::protocol::body::ReqBody;
32//!
33//! #[tokio::main]
34//! async fn main() {
35//! // Initialize logging
36//! let subscriber = FmtSubscriber::builder()
37//! .with_max_level(Level::INFO)
38//! .finish();
39//! tracing::subscriber::set_global_default(subscriber)
40//! .expect("setting default subscriber failed");
41//!
42//! info!(port = 8080, "start listening");
43//! let tcp_listener = match TcpListener::bind("127.0.0.1:8080").await {
44//! Ok(tcp_listener) => tcp_listener,
45//! Err(e) => {
46//! error!(cause = %e, "bind server error");
47//! return;
48//! }
49//! };
50//!
51//! let handler = Arc::new(make_handler(hello_world));
52//!
53//! loop {
54//! let (tcp_stream, _remote_addr) = match tcp_listener.accept().await {
55//! Ok(stream_and_addr) => stream_and_addr,
56//! Err(e) => {
57//! warn!(cause = %e, "failed to accept");
58//! continue;
59//! }
60//! };
61//!
62//! let handler = handler.clone();
63//!
64//! tokio::spawn(async move {
65//! let (reader, writer) = tcp_stream.into_split();
66//! let connection = HttpConnection::new(reader, writer);
67//! match connection.process(handler).await {
68//! Ok(_) => {
69//! info!("finished process, connection shutdown");
70//! }
71//! Err(e) => {
72//! error!("service has error, cause {}, connection shutdown", e);
73//! }
74//! }
75//! });
76//! }
77//! }
78//!
79//! async fn hello_world(request: Request<ReqBody>) -> Result<Response<String>, Box<dyn Error + Send + Sync>> {
80//! let path = request.uri().path().to_string();
81//! info!("request path {}", path);
82//!
83//! let (_header, body) = request.into_parts();
84//!
85//! let body_bytes = body.collect().await?.to_bytes();
86//! info!(body = std::str::from_utf8(&body_bytes[..]).unwrap(), "receiving request body");
87//!
88//! let response_body = "Hello World!\r\n";
89//! let response = Response::builder()
90//! .status(StatusCode::OK)
91//! .header(http::header::CONTENT_LENGTH, response_body.len())
92//! .body(response_body.to_string())
93//! .unwrap();
94//!
95//! Ok(response)
96//! }
97//! ```
98//!
99//!
100//! # Architecture
101//!
102//! The crate is organized into several key modules:
103//!
104//! - [`connection`]: Core connection handling and lifecycle management
105//! - [`protocol`]: Protocol types and abstractions
106//! - [`codec`]: Protocol encoding/decoding implementation
107//! - [`handler`]: Request handler traits and utilities
108//!
109//!
110//!
111//! # Core Components
112//!
113//! ## Connection Handling
114//!
115//! The [`connection::HttpConnection`] type is the main entry point for processing HTTP connections.
116//! It manages the full lifecycle of connections including:
117//!
118//! - Request parsing
119//! - Body streaming
120//! - Response generation
121//! - Keep-alive handling
122//!
123//! ## Request Processing
124//!
125//! Requests are processed through handler functions that implement the [`handler::Handler`] trait.
126//! The crate provides utilities for creating handlers from async functions through
127//! [`handler::make_handler`].
128//!
129//! ## Body Streaming
130//!
131//! Request and response bodies are handled through streaming interfaces that implement
132//! the `http_body::Body` trait. This enables efficient processing of large payloads
133//! without buffering entire bodies in memory.
134//!
135//! ## Error Handling
136//!
137//! The crate uses custom error types that implement `std::error::Error`:
138//!
139//! - [`protocol::HttpError`]: Top-level error type
140//! - [`protocol::ParseError`]: Request parsing errors
141//! - [`protocol::SendError`]: Response sending errors
142//!
143//! # Performance Considerations
144//!
145//! The implementation focuses on performance through:
146//!
147//! - Zero-copy parsing where possible
148//! - Efficient buffer management
149//! - Streaming processing of bodies
150//! - Concurrent request/response handling
151//! - Connection keep-alive
152//!
153//! # Limitations
154//!
155//! - HTTP/1.1 only (currently HTTP/2 or HTTP/3 is not supported)
156//! - No TLS support (use a reverse proxy for HTTPS)
157//! - Maximum header size: 8KB
158//! - Maximum number of headers: 64
159//!
160//! # Safety
161//!
162//! The crate uses unsafe code in a few well-documented places for performance
163//! optimization, particularly in header parsing. All unsafe usage is carefully
164//! reviewed and tested.
165
166pub mod codec;
167pub mod connection;
168pub mod handler;
169pub mod protocol;
170
171mod utils;
172pub(crate) use utils::ensure;