Skip to content

pradyut4u/Web-Server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Async HTTP Server & Web App from Scratch This is a complete, high-performance, asynchronous HTTP web server and application framework built from the ground up in Python. It uses only built-in Python libraries (like asyncio, socket, ssl, sqlite3) and has zero third-party dependencies.

The primary goal of this project is to demonstrate a fundamental, low-level understanding of web protocols and modern server architecture by manually implementing every feature, from socket handling to database persistence.

The server currently hosts a complete portfolio resume page, handles POST requests, and saves user messages to a persistent SQLite database.

🚀 Key Features Asynchronous & Concurrent: Built on asyncio to handle thousands of simultaneous connections on a single thread.

Hybrid Threading Model: Uses a ThreadPoolExecutor (asyncio.to_thread) to offload all blocking I/O (file reads, database writes), preventing the main event loop from ever blocking.

Persistent Database: Integrated with aiosqlite to save user data (sessions, contact form messages) so it survives server restarts.

Dynamic Regex Router: A custom Router class that uses regular expressions to map dynamic URLs (e.g., /profile/alice) to handler functions.

Full POST Handling:

Parses application/x-www-form-urlencoded for text-based forms.

Parses multipart/form-data for file uploads, saving files to the server.

Session Management: Creates a unique session ID (UUID) for new users and tracks them using secure, HttpOnly cookies.

Server-Side Templating: A simple template engine replaces placeholders (like {{VISIT_COUNT}}) in HTML files before serving.

Production-Grade Security:

HTTPS/SSL: Runs on https:// using the ssl module (for local dev).

Path Traversal Mitigation: Actively prevents "dot-dot-slash" (../) attacks by sanitizing all file paths.

MIME-Type Handling: Correctly serves static assets like CSS, JavaScript, and images using the mimetypes library.

Production Ready: The final server is refactored to run as a pure http app server on 127.0.0.1:8000, designed to be run behind a professional reverse proxy like Nginx. A complete nginx.conf is included.

🛠️ Evolution & Technical Deep Dive This server was built iteratively, with each level solving a critical problem of the previous one.

Level 1: The Concurrency Problem Problem: A simple socket.accept() loop is blocking. It can only handle one client at a time, forcing all other users to wait in line.

Inefficient Solution (threading): The first fix was to spawn a new thread for every connection. This works, but it's resource-heavy and does not scale to thousands of users (this is the C10k problem).

Level 2: The C10k Problem Problem: The multi-threaded model is slow and limited by the OS.

Efficient Solution (asyncio): The server was rebuilt on asyncio. It now uses a single-threaded event loop to manage all connections. Network I/O (await reader.read()) is non-blocking, allowing the server to handle thousands of connections concurrently with minimal resource overhead.

Level 3: The Blocking I/O Problem Problem: Even an asyncio server can be blocked. A "slow" operation like reading a large file from disk (open(...).read()) or a slow database query would freeze the entire event loop, blocking all other users.

Solution (Hybrid Model): We implemented the best-of-both-worlds architecture.

The asyncio event loop handles all high-speed network I/O.

All blocking I/O (like file and database access) is delegated to a separate ThreadPoolExecutor using asyncio.to_thread.

This ensures the main loop never blocks and is always free to handle new requests, resulting in a highly performant and scalable server.

Level 4: The Security Problem Problem: A naive file server is vulnerable to Path Traversal. A user could request GET /../server.py and steal the server's source code.

Solution (Path Sanitization): We "jail" the file server. Every file path is resolved to its absolute path (os.path.abspath). The server then verifies that this resolved path still starts with the WEB_ROOT directory. If it doesn't, it returns a 403 Forbidden and logs the security attempt.

Level 5: The Static Content Problem Problem: The browser would receive style.css but render it as plain text because the server sent Content-Type: text/html.

Solution (MIME Types): The server uses the mimetypes library to guess a file's type based on its extension (e.g., .css -> text/css, .png -> image/png) and sends the correct Content-Type header, so the browser renders it properly.

Level 6: The "Static-Only" Problem Problem: The server could only GET files. It had no way to receive data from a user.

Solution (Application Framework): We built a true application framework on top of the server:

POST Handling: Logic was added to parse both application/x-www-form-urlencoded (for text forms) and multipart/form-data (for file uploads).

Regex Router: A Router class was built to match incoming paths against a list of regular expressions, allowing for dynamic routes like /profile/.

Session Management: The server issues a secure HttpOnly cookie to track user sessions.

Database Persistence: The SESSIONS dictionary and "Contact Me" form submissions are saved to a SQLite database, making user data persistent across server restarts.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors