Skip to content

Commit

Permalink
docs: add document to this lib
Browse files Browse the repository at this point in the history
  • Loading branch information
zavakid committed Dec 14, 2024
1 parent 2f9c329 commit ae21e94
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 0 deletions.
125 changes: 125 additions & 0 deletions crates/http/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,128 @@
//! An asynchronous micro HTTP server implementation
//!
//! This crate provides a lightweight, efficient, and modular HTTP/1.1 server implementation
//! built on top of tokio. It focuses on providing a clean API while maintaining high performance
//! through careful memory management and asynchronous processing.
//!
//! # Features
//!
//! - Full HTTP/1.1 protocol support
//! - Asynchronous I/O using tokio
//! - Streaming request and response bodies
//! - Chunked transfer encoding
//! - Keep-alive connections
//! - Expect-continue mechanism
//! - Efficient memory usage through zero-copy parsing
//! - Clean error handling
//!
//!
//! # Example
//!
//! ```no_run
//! use http::{Request, Response, StatusCode};
//! use std::error::Error;
//! use std::sync::Arc;
//! use tokio::net::TcpListener;
//! use micro_http::connection::HttpConnection;
//! use micro_http::handler::make_handler;
//! use micro_http::protocol::body::ReqBody;
//!
//! #[tokio::main]
//! async fn main() {
//! // Create TCP listener
//! let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();
//!
//! // Create handler
//! let handler = Arc::new(make_handler(hello_world));
//!
//! // Accept connections
//! loop {
//! let (stream, _) = listener.accept().await.unwrap();
//! let handler = handler.clone();
//!
//! // Spawn connection handler
//! tokio::spawn(async move {
//! let (reader, writer) = stream.into_split();
//! let connection = HttpConnection::new(reader, writer);
//! connection.process(handler).await.unwrap();
//! });
//! }
//! }
//!
//! // Request handler
//! async fn hello_world(req: Request<ReqBody>) -> Result<Response<String>, Box<dyn Error + Send + Sync>> {
//! Ok(Response::new("Hello World!".to_string()))
//! }
//! ```
//!
//!
//! # Architecture
//!
//! The crate is organized into several key modules:
//!
//! - [`connection`]: Core connection handling and lifecycle management
//! - [`protocol`]: Protocol types and abstractions
//! - [`codec`]: Protocol encoding/decoding implementation
//! - [`handler`]: Request handler traits and utilities
//!
//!
//!
//! # Core Components
//!
//! ## Connection Handling
//!
//! The [`connection::HttpConnection`] type is the main entry point for processing HTTP connections.
//! It manages the full lifecycle of connections including:
//!
//! - Request parsing
//! - Body streaming
//! - Response generation
//! - Keep-alive handling
//!
//! ## Request Processing
//!
//! Requests are processed through handler functions that implement the [`handler::Handler`] trait.
//! The crate provides utilities for creating handlers from async functions through
//! [`handler::make_handler`].
//!
//! ## Body Streaming
//!
//! Request and response bodies are handled through streaming interfaces that implement
//! the `http_body::Body` trait. This enables efficient processing of large payloads
//! without buffering entire bodies in memory.
//!
//! ## Error Handling
//!
//! The crate uses custom error types that implement `std::error::Error`:
//!
//! - [`protocol::HttpError`]: Top-level error type
//! - [`protocol::ParseError`]: Request parsing errors
//! - [`protocol::SendError`]: Response sending errors
//!
//! # Performance Considerations
//!
//! The implementation focuses on performance through:
//!
//! - Zero-copy parsing where possible
//! - Efficient buffer management
//! - Streaming processing of bodies
//! - Concurrent request/response handling
//! - Connection keep-alive
//!
//! # Limitations
//!
//! - HTTP/1.1 only (currently HTTP/2 or HTTP/3 is not supported)
//! - No TLS support (use a reverse proxy for HTTPS)
//! - Maximum header size: 8KB
//! - Maximum number of headers: 64
//!
//! # Safety
//!
//! The crate uses unsafe code in a few well-documented places for performance
//! optimization, particularly in header parsing. All unsafe usage is carefully
//! reviewed and tested.

pub mod codec;
pub mod connection;
pub mod handler;
Expand Down
57 changes: 57 additions & 0 deletions crates/http/src/protocol/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,60 @@
//! Core HTTP protocol abstractions and implementations.
//!
//! This module provides the fundamental building blocks for HTTP protocol handling,
//! including request/response processing, body streaming, and error handling.
//! The design focuses on providing clean abstractions while maintaining high performance
//! and memory efficiency.
//!
//! # Architecture
//!
//! The protocol module is organized into several key components:
//!
//! - **Message Handling** ([`message`]): Core message types and payload processing
//! - [`Message`]: Represents either headers or payload chunks
//! - [`PayloadItem`]: Handles individual payload chunks and EOF
//! - [`PayloadSize`]: Tracks payload size information
//!
//! - **Request Processing** ([`request`]): Request header handling
//! - [`RequestHeader`]: Wraps HTTP request headers with additional functionality
//!
//! - **Response Processing** ([`response`]): Response header handling
//! - [`ResponseHead`]: Type alias for response headers before body attachment
//!
//! - **Body Streaming** ([`body`]): Efficient body handling implementation
//! - [`ReqBody`]: Consumer side implementing `http_body::Body`
//! - [`ReqBodySender`]: Producer side for streaming body chunks
//!
//! - **Error Handling** ([`error`]): Comprehensive error types
//! - [`HttpError`]: Top-level error type
//! - [`ParseError`]: Request parsing errors
//! - [`SendError`]: Response sending errors
//!
//! # Design Goals
//!
//! 1. **Memory Efficiency**
//! - Stream request/response bodies instead of buffering
//! - Implement proper backpressure mechanisms
//!
//! 2. **Clean Abstractions**
//! - Provide intuitive interfaces for protocol handling
//! - Hide implementation complexity from consumers
//!
//! 3. **Protocol Correctness**
//! - Ensure proper HTTP protocol compliance
//! - Handle edge cases and error conditions gracefully
//!
//! 4. **Performance**
//! - Minimize allocations and copies
//! - Support concurrent processing where beneficial
//!
//! # Example Usage
//!
//! The protocol module is typically used through the connection layer rather than
//! directly. However, understanding its components is crucial for implementing
//! custom handlers or extending functionality.
//!
//! See individual module documentation for specific usage examples.
mod message;
pub use message::Message;
pub use message::PayloadItem;
Expand Down
39 changes: 39 additions & 0 deletions crates/http/src/protocol/request.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
//! HTTP request header handling implementation.
//!
//! This module provides the core abstractions for handling HTTP request headers.
//! It wraps the standard `http::Request` type to provide additional functionality
//! specific to our HTTP server implementation.
use std::convert::Into;

use http::request::Parts;
use http::{HeaderMap, Method, Request, Uri, Version};

/// Represents an HTTP request header.
///
/// This struct wraps a `http::Request<()>` to provide:
/// - Access to standard HTTP header fields
/// - Conversion from different request formats
/// - Body attachment capabilities
/// - Request metadata inspection
#[derive(Debug)]
pub struct RequestHeader {
inner: Request<()>,
Expand All @@ -22,49 +34,75 @@ impl AsMut<Request<()>> for RequestHeader {
}

impl RequestHeader {
/// Consumes the header and returns the inner `Request<()>`.
pub fn into_inner(self) -> Request<()> {
self.inner
}

/// Attaches a body to this header, converting it into a full `Request<T>`.
///
/// This is typically used after header parsing to attach the parsed body.
pub fn body<T>(self, body: T) -> Request<T> {
self.inner.map(|_| body)
}

/// Returns a reference to the request's HTTP method.
pub fn method(&self) -> &Method {
self.inner.method()
}

/// Returns a reference to the request's URI.
pub fn uri(&self) -> &Uri {
self.inner.uri()
}

/// Returns the request's HTTP version.
pub fn version(&self) -> Version {
self.inner.version()
}

/// Returns a reference to the request's headers.
pub fn headers(&self) -> &HeaderMap {
self.inner.headers()
}

/// Determines if this request requires a body based on its HTTP method.
///
/// Returns false for methods that typically don't have bodies:
/// - GET
/// - HEAD
/// - DELETE
/// - OPTIONS
/// - CONNECT
pub fn need_body(&self) -> bool {
!matches!(self.method(), &Method::GET | &Method::HEAD | &Method::DELETE | &Method::OPTIONS | &Method::CONNECT)
}
}

/// Converts request parts into a RequestHeader.
impl From<Parts> for RequestHeader {
#[inline]
fn from(parts: Parts) -> Self {
Self { inner: Request::from_parts(parts, ()) }
}
}

/// Converts a bodyless request into a RequestHeader.
impl From<Request<()>> for RequestHeader {
#[inline]
fn from(inner: Request<()>) -> Self {
Self { inner }
}
}

/// Converts a parsed HTTP request into a RequestHeader.
///
/// This implementation handles the conversion from the low-level parsed request
/// format into our RequestHeader type, setting up:
/// - HTTP method
/// - URI/path
/// - HTTP version
/// - Headers
impl<'headers, 'buf> From<httparse::Request<'headers, 'buf>> for RequestHeader {
fn from(req: httparse::Request<'headers, 'buf>) -> Self {
let mut builder = Request::builder()
Expand All @@ -81,6 +119,7 @@ impl<'headers, 'buf> From<httparse::Request<'headers, 'buf>> for RequestHeader {
}
}

/// Helper struct for HTTP version conversion.
struct U8Wrapper(u8);

impl From<U8Wrapper> for Version {
Expand Down
11 changes: 11 additions & 0 deletions crates/http/src/protocol/response.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
//! HTTP response header handling implementation.
//!
//! This module provides type definitions for HTTP response headers.
//! It uses the standard `http::Response` type with an empty body placeholder
//! to represent response headers before the actual response body is attached.
use http::Response;

/// Type alias for HTTP response headers.
///
/// This type represents the header portion of an HTTP response, using
/// `http::Response<()>` with an empty body placeholder. The actual response
/// body can be attached later using the response builder pattern.
pub type ResponseHead = Response<()>;

0 comments on commit ae21e94

Please sign in to comment.