Building a Simple Web Server with Python
When you think of Web development in Python, you might think of popular Web frameworks like Django or Flask. While these are good for large applications used by many people simultaneously, Python’s standard libary is good enough for a small project that’s only used by one person at a time.
I recently created a Web-based tool for sending files across different computers at home, mainly between my desktop computer and laptop. I’ll walk through how I wrote this tool using Python’s standard library modules.
(Yes, I know flash drives exist, but I don’t have any available and I’d rather not buy one if I’m not going to use it very often.)
Basic Web Server with http.server
The http.server module provides classes for building a basic Web server. This isn’t meant to be a complete tutorial (the official documentation is quite good), but I’ll provide a basic outline of how to use the module.
The minimal code to start a server is:
import http.server
server = http.server.HTTPServer(("", 8000), MyRequestHandler)
server.serve_forever()
The first parameter to the HTTPServer
constructor is the server address, which is a tuple consisting of a host address and a port. The host address determines where the server will listen: For example, specifying “localhost” means the server will only listen to connections from the same system, while the empty string means to listen on all interfaces (only for IPv4; to support IPv6 use ::
).
The second parameter is the request handler class, which specifies how requests should be handled. The module provides a BaseHTTPRequestHandler
class you can derive from to build your own handler. The subclass should override the do_METHOD
functions to handle each HTTP method. For example, here is a request handler that simply responds with a 404 to all GET requests:
class NotFoundRequestHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
response_data = b"Not found" # Repsonse data must be sent as bytes
self.send_response(http.HTTPStatus.NOT_FOUND) # Status codes are in the separate http module
self.send_header("Content-Type", "text/plain")
self.send_header("Content-Length", len(response_data))
self.end_headers()
self.wfile.write(response_data)
Web Application in a Single File
For this project, I wanted to keep everything in a single file so that it would be easy to run. I decided to use a single-page application (SPA) architecture, which meant that I only had to serve a single static page and didn’t have to deal with any templating.
The static page for the frontend is a hardcoded string. This page contains an inline script to handle browsing and uploading files via API calls (using old-fashioned JavaScript which should work in Internet Explorer 10 or later).
The backend is the request handler, which handles GET and POST requests:
- GET: If the path is
/
then the handler serves the hardcoded HTML page. Otherwise, it usesSimpleHTTPRequestHandler
(provided by thehttp.server
module) to serve the file at that path. - POST: There are two API endpoints. The
/send
endpoint saves a file and the/dirlist
endpoint returns a directory listing.
Conclusion
Python’s standard library provides decent but fairly rudimentary support for building Web applications. I’ve had to implement things like routing, request parsing, and security checks myself, things that you might expect from a “proper” Web framework. Still, in cases where you don’t need the full power of such a framework, the standard library can be useful.