This is a starting point for Python solutions to the "Build Your Own HTTP server" Challenge.
HTTP is the protocol that powers the web. In this challenge, you'll build a HTTP/1.1 server that is capable of serving multiple clients.
Along the way you'll learn about TCP servers, HTTP request syntax, and more.
Note: If you're viewing this repo on GitHub, head over to codecrafters.io to try the challenge.
A basic asynchronous HTTP server implemented in Python using the asyncio library. The server handles GET and POST requests for echoing text, retrieving user-agent information, and managing files in a specified directory.
- Root Endpoint (
/): Returns a200 OKresponse. - Echo Endpoint (
/echo/{text}): Echoes back the provided text with optional gzip compression if supported by the client. - User-Agent Endpoint (
/user-agent): Returns the client'sUser-Agentheader value. - File Endpoints (
/files/{filename}):- GET: Retrieves a file from the specified directory, with optional gzip compression.
- POST: Creates or overwrites a file in the specified directory with the request body content.
- Error Handling: Returns
404 Not Foundfor invalid endpoints or missing files. - Logging: Logs client connections, requests, and errors with timestamps.
- Python 3.10+
- No external dependencies required (uses standard library modules:
asyncio,socket,gzip,pathlib,logging)
- Clone or download the repository.
- Ensure Python 3.10 or higher is installed.
Run the server using the command below. Optionally, specify a directory for file operations:
./your_program.sh [--directory <path>]- Without directory: The
/files/*endpoints will return404for GET requests and raise an error for POST requests. - With directory: Provide a path for file storage/retrieval (e.g.,
/tmp/files).
Example:
./your_program.sh --directory /tmp/filesThe server listens on localhost:4221 by default.
-
Root:
curl http://localhost:4221/
Response:
HTTP/1.1 200 OK -
Echo:
curl http://localhost:4221/echo/hello
Response:
hello(withContent-Type: text/plain)With compression:
curl -H "Accept-Encoding: gzip" http://localhost:4221/echo/hello --compressed -
User-Agent:
curl -A "Mozilla/5.0" http://localhost:4221/user-agentResponse:
Mozilla/5.0 -
File GET (with
--directory /tmp/files):curl http://localhost:4221/files/example.txt
Response: Contents of
/tmp/files/example.txtor404if not found. -
File POST (with
--directory /tmp/files):curl -X POST --data "Hello, World!" http://localhost:4221/files/example.txtResponse:
HTTP/1.1 201 Created(creates/tmp/files/example.txt).
- HttpReqLine: Parses the HTTP request line (e.g.,
GET /path HTTP/1.1). - HttpHeaders: Handles HTTP headers as a dictionary-like object.
- HttpRequest: Represents a parsed HTTP request with method, path, headers, and body.
- HttpResponse: Constructs HTTP responses with status, headers, and body (supports gzip compression).
- Handlers:
echo_handler: Returns the provided text.user_agent_handler: Returns the client's User-Agent.files_get_handler: Retrieves a file.files_post_handler: Saves a file.
- Main Loop: Uses
asyncioto handle client connections concurrently.
- HOST:
localhost(default) - PORT:
4221(default) - BUFF_SIZE:
1024bytes for receiving data - Directory: Optional, specified via
--directoryargument
The server logs:
- Client connections and disconnections
- Received requests
- Errors (with stack traces)
Example log output:
2025-04-11 18:09:10,420 [SERVER STARTED] Listening on localhost:4221
2025-04-11 18:09:21,940 [CONNECTED] 127.0.0.1:47920
2025-04-11 18:09:21,940 [RECEIVED from 127.0.0.1:47920] b'GET /echo/abc HTTP/1.1\r\nHost: localhost:4221\r\nUser-Agent: curl/8.12.1\r\nAccept: */*\r\nAccept-Encoding: invalid-encoding\r\n\r\n'
2025-04-11 18:09:21,941 [DISCONNECTED] 127.0.0.1:47920
- Minimal error handling for malformed requests.
- No support for advanced HTTP features (e.g., chunked encoding, keep-alive).
- File operations are synchronous and may block the event loop for large files.
- Single-threaded; relies on
asynciofor concurrency.
Test the server using tools like curl, wget, or a browser. For automated testing, consider a framework like pytest with an HTTP client library (e.g., aiohttp).
Example test command:
curl http://localhost:4221/echo/testContributions are welcome! Please:
- Fork the repository.
- Create a feature branch.
- Submit a pull request with clear descriptions.
This project is licensed under the MIT License. See the LICENSE file for details.