A minimal HTTP parser and server library written in Rust. This library provides both a lightweight HTTP request parser and a fully-featured HTTP server implementation.
- Parse HTTP requests from byte slices
- Support for common HTTP methods (GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH)
- Support for HTTP versions 1.0, 1.1, and 2.0
- Proper error handling with descriptive error messages
- Built-in HTTP server with:
- Async/await support using Tokio
- Route registration with method filtering
- Query parameter parsing
- JSON request and response handling
- Custom header support
- Configurable connection limits and buffer sizes
- Graceful shutdown handling
Add this to your Cargo.toml:
[dependencies]
microhttp-rs = "0.1.0"tokio = { version = "1.36.0", features = ["rt", "rt-multi-thread", "io-util", "net", "sync", "macros", "time", "signal"] }use microhttp_rs::{parse_request,HttpRequest,Method,HttpVersion,Error};fnmain(){let request_bytes = b"GET /index.html HTTP/1.1\r\nHost: example.com\r\n\r\n";matchparse_request(request_bytes){Ok(request) => {println!("Method: {}", request.method);println!("Path: {}", request.path);println!("Version: {}", request.version);println!("Headers: {:?}", request.headers);}Err(err) => {println!("Error parsing request: {}", err);}}}The library provides a built-in HTTP server with routing capabilities. Here's a basic example:
use microhttp_rs::{HttpResponse,HttpServer,Method,ServerConfig,StatusCode};#[tokio::main]asyncfnmain() -> Result<(),Box<dyn std::error::Error>>{// Step 1: Create a server configurationlet config = ServerConfig{addr:"127.0.0.1:8080".parse()?,// Server address and portmax_connections:100,// Maximum concurrent connectionsread_buffer_size:4096,// Buffer size for reading requests};// Step 2: Create a new HTTP serverlet server = HttpServer::new(config);// Step 3: Add routes to handle different paths// Simple route that returns "Hello, World!"
server.add_route("/",vec![Method::GET], |_req| asyncmove{Ok(HttpResponse::new(StatusCode::Ok).with_content_type("text/plain").with_body_string("Hello, World!"))}).await;// Route that handles query parameters
server.add_route("/hello",vec![Method::GET], |req| asyncmove{// Get the 'name' query parameter if it existslet name = req.get_query_param("name").map_or("World", |s| s.as_str());Ok(HttpResponse::new(StatusCode::Ok).with_content_type("text/plain").with_body_string(format!("Hello, {}!", name)))}).await;// Step 4: Start the server
server.start().await?;Ok(())}This example demonstrates:
- Creating a server configuration
- Creating a new HTTP server instance
- Adding routes to handle different paths and HTTP methods
- Processing query parameters
- Starting the server
For more advanced examples, see the examples directory in the repository.
The server supports JSON requests and responses:
use microhttp_rs::{HttpResponse,HttpServer,Method,ServerConfig,StatusCode,ServerError};use serde::{Deserialize,Serialize};#[derive(Debug,Serialize,Deserialize)]structUser{name:String,email:String,}#[tokio::main]asyncfnmain() -> Result<(),Box<dyn std::error::Error>>{// Create a server configurationlet config = ServerConfig{addr:"127.0.0.1:8080".parse()?,max_connections:1024,read_buffer_size:8192,};// Create a new HTTP serverlet server = HttpServer::new(config);// Add a route that handles JSON
server.add_route("/api/users",vec![Method::POST], |req| asyncmove{// Check if the request is JSONif !req.is_json(){returnOk(HttpResponse::new(StatusCode::BadRequest).with_content_type("text/plain").with_body_string("Content-Type must be application/json"));}// Parse the JSON bodymatch req.json::<User>(){Ok(user) => {HttpResponse::new(StatusCode::Created).with_json(&user).map_err(|e| ServerError::InternalError(format!("JSON error: {}", e)))},Err(e) => {Ok(HttpResponse::new(StatusCode::BadRequest).with_content_type("text/plain").with_body_string(format!("Invalid JSON: {}", e)))}}}).await;// Start the server
server.start().await?;Ok(())}The library includes several examples in the examples directory:
A basic example showing how to parse HTTP requests:
cargo run --example simple_parserA low-level HTTP server example using the parser directly:
cargo run --example simple_serverThen visit http://localhost:8082 in your browser or use curl:
curl http://localhost:8082/helloA basic example showing how to use the HTTP server API with minimal configuration:
cargo run --example basic_serverThis example demonstrates:
- Setting up a server with basic configuration
- Adding simple routes
- Handling query parameters
- Returning different status codes
You can test it with:
# Get a simple response
curl http://localhost:8081/
# Test the hello endpoint with a query parameter
curl "http://localhost:8081/hello?name=YourName"# Test different status codes
curl "http://localhost:8081/status?code=404"A more comprehensive HTTP server example demonstrating routing, JSON handling, query parameters, and more:
cargo run --example http_serverThis example includes:
- Multiple routes with different HTTP methods
- Query parameter handling
- JSON request and response processing
- Custom headers
- Different status codes
You can test it with:
# Test the hello endpoint with a query parameter
curl "http://localhost:8083/hello?name=YourName"# Test the JSON API
curl -X POST -H "Content-Type: application/json" -d '{"name":"John","email":"john@example.com"}' http://localhost:8083/api/users
# Test different status codes
curl "http://localhost:8083/status?code=404"# View request headers
curl http://localhost:8083/headersThis project is licensed under the MIT License - see the LICENSE file for details.