A high-performance, multithreaded HTTP proxy server written in C. This project demonstrates advanced systems programming concepts including socket programming, POSIX threads, synchronization primitives, and automated response caching.
- Multithreaded Architecture: Uses a "thread-per-request" model to handle hundreds of concurrent client connections efficiently.
- HTTP/1.1 Compliant: Forwards method, path, and headers to remote servers, maintaining protocol integrity.
- Intelligent Caching: Implements a thread-safe LRU (Least Recently Used) caching mechanism to reduce latency for frequently accessed resources.
- Graceful Shutdown: Robust signal handling for
SIGINT(Ctrl+C) ensuring all sockets are closed and memory is freed correctly. - Dynamic Configuration: Easy-to-use command line interface to specify ports and enable/disable features.
.
├── src/
│ ├── main.c # Entry point and server loop
│ ├── proxy.c # Caching and request parsing logic
│ └── server.c # Socket handling and thread management
├── include/
│ └── proxy.h # Global definitions and function prototypes
├── Makefile # Build configuration
├── CMakeLists.txt # Modern CMake build configuration
└── test.sh # Automated testing script
Ensure you have a POSIX-compliant environment (Linux, macOS, or WSL) and theFollowing tools installed:
gccorclangmakeorcmakecurl(for testing)
# Clean previous builds
make clean
# Compile the project
makemkdir build && cd build
cmake ..
makeStart the proxy server by specifying a port:
# Run with caching enabled on port 8080
./proxy_server -p 8080 -c
# Run without caching on port 9000
./proxy_server -p 9000-p <port>: Required. Port on which the proxy will listen.-c: Optional. Enable response caching.-h/--help: Display help message.
You can run the included test script to verify the build and basic functionality:
chmod +x test.sh
./test.shTo route your requests through the proxy:
curl -x http://localhost:8080 http://example.comThe server uses a master loop that accepts new connections. For every connection, a new detached POSIX thread is created. This allows the server to remain responsive while waiting for remote server responses.
The cache is implemented as an array of entries protected by a pthread_mutex. When a request is made, the proxy generates a key based on Host + Path.
- Cache Hit: Returns the response immediately from memory.
- Cache Miss: Fetches from the remote server, serves the client, and updates the cache.
- Eviction: When the cache is full, the entry with the oldest timestamp is evicted to make room for new data.
The project uses strtok_r for thread-safe string parsing and ensures all dynamically allocated memory (requests, responses, thread arguments) is properly freed, even in error paths.
This project is licensed under the MIT License - see the LICENSE file for details.
Created with ❤️ by Aditya (Aditya41150)