Creating a Python Web Server: From Basic to Advanced

Anshu Pal
4 min readJan 24, 2023

--

Introduction: Setting up a Simple Web Server in Python

In this tutorial, we will learn how to create a simple web server in Python using the http.server module. We will cover how to handle both GET and POST requests, and serve HTML files and dynamic responses.

To create a simple web server, we will utilize the HTTPServer class from the http.server module and create a custom request handler class that inherits from BaseHTTPRequestHandler. We will then override the do_GET() and do_POST() methods to handle the requests.

from http.server import HTTPServer, BaseHTTPRequestHandler

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b'Hello, World!')

httpd = HTTPServer(('', 8000), SimpleHTTPRequestHandler)
httpd.serve_forever()

You can run this script on your local machine and then use a web browser to visit http://localhost:8000/ and you should see "Hello, World!"

Handling GET Requests: Serving HTML files and Default Paths

In the do_GET() method, we will serve HTML files and handle the default path '/' by redirecting it to '/index.html'. We will also handle the case when a requested file is not found by returning a 404 error message.

from http.server import HTTPServer, BaseHTTPRequestHandler

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

def do_GET(self):
if self.path == '/':
self.path = '/index.html'
try:
file_to_open = open(self.path[1:]).read()
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(bytes(file_to_open, 'utf-8'))
except:
self.send_response(404)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(b'404 - Not Found')

httpd = HTTPServer(('', 8000), SimpleHTTPRequestHandler)
httpd.serve_forever()

In this example, the do_GET() method checks if the request path is '/', if it is then it changes the path to '/index.html' so that it can serve the index.html file by default. It then tries to open the requested file using open(self.path[1:]).read() and if it is able to open it, it sends the file to the client by setting the response code to 200, the content type to 'text/HTML, and the body to the file content. If it is not able to open the file it sends a 404 response with the message '404 - Not Found'

Handling POST Requests: Parsing Form Data and Sending Responses

For handling POST requests, we will use the cgi module to parse the form data sent in the request body and read the values of the form fields. Additionally, we will demonstrate how to use a template engine such as Jinja2 to render the index.html file with dynamic data, which can be useful for generating dynamic responses to the client.

from http.server import HTTPServer, BaseHTTPRequestHandler
import cgi

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

def do_GET(self):
if self.path == '/':
self.path = '/index.html'
try:
file_to_open = open(self.path[1:]).read()
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(bytes(file_to_open, 'utf-8'))
except:
self.send_response(404)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(b'404 - Not Found')

def do_POST(self):
# Parse the form data
form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={'REQUEST_METHOD': 'POST',
'CONTENT_TYPE': self.headers['Content-Type'],
}
)

# Get the form values
first_name = form.getvalue("first_name")
last_name = form.getvalue("last_name")

self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(b'Hello, ' + first_name.encode() + b' ' + last_name.encode())

httpd = HTTPServer(('', 8000), SimpleHTTPRequestHandler)
httpd.serve_forever()

In this example, the do_POST() method uses the cgi module to parse the form data sent in the request body, and then it reads the values of the form fields by calling the getvalue() method on the FieldStorage object. Then it sends a response back to the client with a message that greets the user with their first name and last name.

You can test this by creating an HTML form that sends a POST request to http://localhost:8000/ with the fields "first_name" and "last_name". When you submit the form, the server should respond with a message that greets you by your first and last name.

Dynamic Responses: Using a Template Engine to Render HTML Files

To send a dynamic response to the index.html file after a GET request, you can use a template engine such as Jinja2 to render the index.html file with dynamic data. Here's an example of how you can use Jinja2 to render the index.html file with a message variable:

from http.server import HTTPServer, BaseHTTPRequestHandler
from jinja2 import Environment, FileSystemLoader

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.path = '/index.html'
try:
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template(self.path[1:])
message = "Hello, World!"
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(bytes(template.render(message=message), 'utf-8'))
except:
self.send_response(404)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(b'404 - Not Found')

httpd = HTTPServer(('', 8000), SimpleHTTPRequestHandler)
httpd.serve_forever()

In this example, the do_GET() method uses the Environment and FileSystemLoader classes from the Jinja2 library to create an instance of the template engine, and load the index.html file using the get_template() method.

The Road Ahead: Building on the foundation of a simple web server in Python

In conclusion, creating a simple web server in Python is a relatively easy task, but it provides a solid foundation for building more advanced web applications. We have covered the basics of handling GET and POST requests and serving HTML files, as well as more advanced techniques such as using a template engine to render dynamic responses.

This tutorial was designed to provide a comprehensive guide for beginners to understand the basics of web servers and how to set one up in Python. The simple web server created in this tutorial can be used as a starting point for your own projects and can be expanded and customized to suit your needs.

It is important to note that this tutorial only covers the basics of web servers, and there are many more features and functionalities that can be added to your web server, such as handling different types of files, authentication and authorization, handling errors, and more. The possibilities are endless, and I hope this tutorial has provided you with the knowledge and confidence to start building your own web applications using Python.

--

--

Anshu Pal

I’m a web developer. I spend my whole day, practically every day, experimenting with HTML, CSS, and JavaScript.