This project implements a lightweight HTTP server from scratch using only Python’s built-in libraries (socket, threading, os, gzip).
It supports basic REST-like endpoints for file upload/download, echo messages, user-agent inspection, and gzip compression.
Supports GET and POST methods
Handles /, /echo/<message>, /user-agent, and /files/<filename> routes
File upload via POST /files/<filename>
File download via GET /files/<filename>
Optional gzip compression for /echo/ responses
Correct Content-Length, Content-Type, and Connection headers
Graceful Connection: close handling
Multi-threaded connections — handles multiple clients simultaneously
No external dependencies (pure Python)
- Python 3.9+
- No external packages needed
Run the server on port 4221:
python server.pyTo serve or upload files, specify a directory with --directory:
python server.py --directory ./files/ — Root
Simple health check endpoint.
Request:
GET /
Response:
HTTP/1.1 200 OK
/echo/ — Echo
Returns the message back to the client. Supports gzip if Accept-Encoding: gzip header is provided.
Example 1 (plain):
GET /echo/hello
Response:
HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 5
Example 2 (gzip-compressed):
GET /echo/hello Accept-Encoding: gzip
Response Headers:
HTTP/1.1 200 OK Content-Encoding: gzip Content-Type: text/plain Content-Length: <compressed_size>
/user-agent — Return User-Agent Header
Extracts and returns the User-Agent header value from the request.
Request:
GET /user-agent User-Agent: Mozilla/5.0
Response:
HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 11
Mozilla/5.0
/files/ — File Handling
Uploads a file to the given directory.
Request:
POST /files/example.txt Content-Length: 11
Hello World
Response:
HTTP/1.1 201 Created
This creates ./files/example.txt containing Hello World.
Downloads a file from the server.
Request:
GET /files/example.txt
Response:
HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Length: 11
Hello World
If the file does not exist:
HTTP/1.1 404 Not Found
Command-Line Arguments Argument Description Default --directory Path to serve files from (None)
Example:
python server.py --directory ./uploadsHow It Works
- Socket Server
Creates a TCP server using:
socket.create_server(("localhost", 4221), reuse_port=True)
Each connection is handled in a new thread (threading.Thread).
- Request Parsing
Reads data until a full HTTP header (\r\n\r\n) is received. Splits the first line into method, path, and protocol.
- Routing
Depending on the request path and method, routes to:
handle_root()
handle_echo()
handle_user_agent()
handle_file() / handle_post()
- Gzip Handling
For /echo/ endpoint — compresses output if the request header includes Accept-Encoding: gzip.
- Connection Handling
Supports persistent connections (keeps the socket open)
Closes if header Connection: close is present
Echo endpoint:
curl http://localhost:4221/echo/HelloEcho with gzip:
curl -H "Accept-Encoding: gzip" http://localhost:4221/echo/Hello --output - | gunzipUpload a file:
curl -X POST --data-binary "Hello World" http://localhost:4221/files/test.txtDownload it:
curl http://localhost:4221/files/test.txtUser-Agent endpoint:
curl -H "User-Agent: MyCustomAgent" http://localhost:4221/user-agent