A complete Rust-based HTTP server and client setup for local testing using Axum framework and tmux sessions.
This project demonstrates a classic client-server architecture where:
- Server: A REST API built with Axum that handles HTTP requests
- Client: A command-line application that sends HTTP requests to the server
- Communication: HTTP/JSON over TCP on localhost
- Isolation: Both run in separate tmux sessions for independent monitoring
Think of this setup like a restaurant system:
-
Server = Kitchen π¨βπ³
- Receives orders (HTTP requests)
- Processes them (business logic)
- Sends back food (HTTP responses)
- Keeps track of all orders (in-memory storage)
-
Client = Customer/Waiter π€
- Places orders (sends HTTP requests)
- Receives responses (gets the food)
- Can check what's available (health check)
- Can see order history (get messages)
-
tmux Sessions = Separate dining rooms π’
- Kitchen operates independently in one room
- Customer area in another room
- You can peek into either room anytime
- Both can work simultaneously
axum-test/
βββ Cargo.toml # Project dependencies
βββ README.md # This file
βββ setup-tmux.sh # Automated setup script
βββ src/
βββ main.rs # Default main (unused)
βββ bin/
βββ server.rs # HTTP server implementation
βββ client.rs # HTTP client implementation
[dependencies]
axum = "0.7" # Web framework
tokio = { version = "1.0", features = ["full"] } # Async runtime
serde = { version = "1.0", features = ["derive"] } # Serialization
serde_json = "1.0" # JSON support
reqwest = { version = "0.11", features = ["json"] } # HTTP client
Message {
id: u32, // Unique identifier
content: String, // Message text
timestamp: String, // Unix timestamp
}
- Uses
OnceLock<Arc<Mutex<AppState>>>
for thread-safe global state - Why this approach?
OnceLock
: Initialize once, use everywhereArc
: Shared ownership across threadsMutex
: Mutual exclusion for safe mutations- Alternative: In production, use databases like PostgreSQL/MongoDB
Method | Endpoint | Purpose | Example Response |
---|---|---|---|
GET |
/ |
Server status | "π¦ Axum Server is running!" |
GET |
/health |
Health check | {"status": "healthy", "timestamp": 1234567890} |
GET |
/messages |
List all messages | [{"id": 1, "content": "Hello", "timestamp": "1234567890"}] |
GET |
/messages?limit=5 |
List limited messages | Same as above, but max 5 items |
POST |
/messages |
Create new message | {"id": 2, "content": "New message", "timestamp": "1234567891"} |
- Returns appropriate HTTP status codes
- Validates input (empty messages rejected with
400 Bad Request
) - Thread-safe operations with proper error propagation
The client provides a simple CLI interface:
π§ Axum Test Client
Server: http://127.0.0.1:9090
Commands:
1 - Health check (GET /health)
2 - Get all messages (GET /messages)
3 - Create new message (POST /messages)
q - Quit
- HTTP Client: Uses
reqwest
for making HTTP requests - JSON Handling: Automatic serialization/deserialization
- Error Handling: Displays user-friendly error messages
- Interactive: Real-time communication with server
- Rust 1.70+ installed
- tmux installed (
brew install tmux
on macOS)
- Clone and setup project:
cargo new axum-test --bin
cd axum-test
# Copy the provided Cargo.toml and source files
- Automated setup with tmux:
chmod +x setup-tmux.sh
./setup-tmux.sh
- Manual setup:
# Terminal 1: Start server
cargo run --bin server
# Terminal 2: Start client
cargo run --bin client
# Create server session
tmux new-session -d -s axum-server -c "$(pwd)" "cargo run --bin server"
# Create client session
tmux new-session -d -s axum-client -c "$(pwd)" "cargo run --bin client"
# List all sessions
tmux list-sessions
# Attach to server session (see server logs)
tmux attach-session -t axum-server
# Attach to client session (interact with API)
tmux attach-session -t axum-client
# Detach from current session
Ctrl+b, then d
# Kill sessions
tmux kill-session -t axum-server
tmux kill-session -t axum-client
- Start server β See startup logs
- Start client β Connect to server
- Health check β Verify server is responding
- Create messages β Add some test data
- Retrieve messages β Verify data persistence
- Monitor server logs β See request processing
> 1 # Health check
β
Server is healthy
> 3 # Create message
Enter message content: Hello, World!
β
Created message: [1] Hello, World!
> 3 # Create another
Enter message content: Testing API
β
Created message: [2] Testing API
> 2 # Get all messages
π¬ Found 2 messages:
[1] Hello, World! (1734567890)
[2] Testing API (1734567891)
- β Handle multiple concurrent HTTP requests
- β Store data in memory (thread-safe)
- β Provide RESTful API endpoints
- β Return JSON responses
- β Validate input data
- β Generate unique IDs automatically
- β Timestamp messages
- β
Handle query parameters (
?limit=N
) - β Provide health monitoring
- β Log all operations to console
- β Make HTTP GET/POST requests
- β Handle JSON serialization/deserialization
- β Interactive command-line interface
- β Display formatted responses
- β Handle network errors gracefully
- β Real-time communication with server
- β Hot reloading (restart to see code changes)
- β Separate monitoring of server and client
- β Real-time log viewing
- β Easy session management with tmux
- β Local development environment
- β No external dependencies (runs offline)
- β HTTP protocol understanding
- β REST API design patterns
- β Async programming in Rust
- β Thread-safe programming
- β JSON handling
- β Error handling patterns
- β Client-server architecture
- β No persistent storage - Data lost on server restart
- β No authentication/authorization - Anyone can access
- β No HTTPS/TLS - Communication not encrypted
- β No rate limiting - Vulnerable to spam/DoS
- β No input sanitization - Basic validation only
- β No logging framework - Just println! statements
- β No configuration management - Hardcoded values
- β No environment separation - Only works locally
- β Single server instance - No load balancing
- β Memory-only storage - Limited by RAM
- β No database - Can't handle large datasets
- β No caching - Every request hits main storage
- β No connection pooling - Basic HTTP handling
- β No horizontal scaling - Can't distribute load
- β No health monitoring - Basic health endpoint only
- β No metrics collection - No performance data
- β No graceful shutdown - Abrupt termination
- β No backup/recovery - Data loss on crash
- β No monitoring/alerting - No operational visibility
- β No deployment automation - Manual setup only
- β HTTP only - No WebSocket support
- β No GraphQL - REST API only
- β No file uploads - Text messages only
- β No streaming - Request/response only
- β No real-time updates - Polling required
- β No compression - Raw JSON responses
- β No input validation - Basic checks only
- β No SQL injection protection - Not applicable (no DB)
- β No CORS handling - Browser limitations
- β No request size limits - Memory exhaustion possible
- β No timeout handling - Long requests can hang
- β No audit logging - No security trail
-
Database Integration
// Add to Cargo.toml sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres"] }
-
Authentication
// Add JWT or session-based auth jsonwebtoken = "8.3"
-
Configuration
// Environment-based config serde_env = "0.1"
-
Logging
// Structured logging tracing = "0.1" tracing-subscriber = "0.3"
- Docker containerization
- Kubernetes deployment
- CI/CD pipelines
- API documentation with OpenAPI
- Integration testing
- Performance benchmarking
- Microservices architecture
# Check if port is in use
lsof -i :9090
# Kill existing process
kill -9 <PID>
# Verify server is running
curl http://127.0.0.1:9090/health
# Check firewall settings
# Ensure both client and server use same port
# List all sessions
tmux list-sessions
# Kill all sessions
tmux kill-server
# Restart tmux
tmux new-session
# Clean build
cargo clean
cargo build
# Update dependencies
cargo update
This project serves as an excellent introduction to:
- Web Development: Understanding HTTP protocols, REST APIs, and client-server communication
- Rust Programming: Async programming, ownership, threading, and error handling
- DevOps Practices: Process management with tmux, local development setup
- API Design: RESTful endpoints, JSON serialization, status codes
- Testing Strategies: Manual testing, client simulation, integration testing
Feel free to extend this project with:
- Database integration
- Authentication mechanisms
- More endpoints
- Better error handling
- Configuration management
- Docker containerization
- Integration tests
This project is for educational purposes. Feel free to use and modify as needed.
Happy Coding! π¦