Introduction

Python's built-in web server is a simple, yet powerful tool that allows you to quickly set up a web server for development and testing purposes. It is part of Python's http.server module, which provides classes for implementing web servers.

This guide shows you how to use the Python http.server module.

Prerequisites

Before you begin:

  • Deploy a VPS server. For instance, Ubuntu 24.04.
  • Create a non-root sudo user.
  • Install Python.

Simple Hello, World! Web Server

Start with a simple example that serves a Hello, World! message by following the steps below.

  1. Create a new Python file (e.g., server.py) and add the following code:

    Python
    from http.server import BaseHTTPRequestHandler, HTTPServer
    
    class HelloWorldHandler(BaseHTTPRequestHandler):
        def do_GET(self):
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(b'Hello, World!')
    
    def run(server_class=HTTPServer, handler_class=HelloWorldHandler, port=8000):
        server_address = ('', port)
        httpd = server_class(server_address, handler_class)
        print(f'Starting server on port {port}...')
        httpd.serve_forever()
    
    if __name__ == '__main__':
        run()
    
  2. Run the server:

    Bash
    $ python3 server.py
    
  3. Access the web server: Open a web browser and navigate to:

    ``` http://localhost:8000 ````.

    You should see "Hello, World!" displayed on the page.

Handling Different HTTP Methods

Now that we you've a basic web server running, extend it to handle different HTTP methods.

GET Requests

You've already seen how to handle a basic GET request. Extend this by adding more functionality to our handler.

POST Requests

Add the following method to handle POST requests:

Python
def do_POST(self):
    content_length = int(self.headers['Content-Length'])
    post_data = self.rfile.read(content_length)
    self.send_response(200)
    self.send_header('Content-type', 'text/html')
    self.end_headers()
    response = f'POST request received: {post_data.decode("utf-8")}'
    self.wfile.write(response.encode('utf-8'))

PUT Requests

Add the following method to handle PUT requests:

Python
def do_PUT(self):
    content_length = int(self.headers['Content-Length'])
    put_data = self.rfile.read(content_length)
    self.send_response(200)
    self.send_header('Content-type', 'text/html')
    self.end_headers()
    response = f'PUT request received: {put_data.decode("utf-8")}'
    self.wfile.write(response.encode('utf-8'))

DELETE Requests

Add the following method to handle DELETE requests:

Python
def do_DELETE(self):
    self.send_response(200)
    self.send_header('Content-type', 'text/html')
    self.end_headers()
    self.wfile.write(b'DELETE request received')

PATCH Requests

Add the following method to handle PATCH requests:

Python
def do_PATCH(self):
    content_length = int(self.headers['Content-Length'])
    patch_data = self.rfile.read(content_length)
    self.send_response(200)
    self.send_header('Content-type', 'text/html')
    self.end_headers()
    response = f'PATCH request received: {patch_data.decode("utf-8")}'
    self.wfile.write(response.encode('utf-8'))

Your updated server code should look like this:

Python
from http.server import BaseHTTPRequestHandler, HTTPServer

class MyRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'Hello, World!')

    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        response = f'POST request received: {post_data.decode("utf-8")}'
        self.wfile.write(response.encode('utf-8'))

    def do_PUT(self):
        content_length = int(self.headers['Content-Length'])
        put_data = self.rfile.read(content_length)
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        response = f'PUT request received: {put_data.decode("utf-8")}'
        self.wfile.write(response.encode('utf-8'))

    def do_DELETE(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'DELETE request received')

    def do_PATCH(self):
        content_length = int(self.headers['Content-Length'])
        patch_data = self.rfile.read(content_length)
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        response = f'PATCH request received: {patch_data.decode("utf-8")}'
        self.wfile.write(response.encode('utf-8'))

def run(server_class=HTTPServer, handler_class=MyRequestHandler, port=8000):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print(f'Starting server on port {port}...')
    httpd.serve_forever()

if __name__ == '__main__':
    run()

Send Requests Using curl

You can test your web server by sending requests using curl, a command-line tool for transferring data with URLs. Here are some examples of how to use curl for the different HTTP methods:

  1. Send a GET request to the root path:

    Bash
    curl http://localhost:8000
    
  2. Send a POST request with data:

    Bash
    curl -X POST -d "name=Francis" http://localhost:8000
    
  3. Send a PUT request with data:

    Bash
    curl -X PUT -d "name=UpdatedName" http://localhost:8000
    
  4. Send a DELETE request:

    Bash
    curl -X DELETE http://localhost:8000
    
  5. Send a PATCH request with data:

    Bash
    curl -X PATCH -d "name=PatchedName" http://localhost:8000
    

You can use curl to test different endpoints and verify that your web server is handling requests correctly.

Conclusion

This guide explains how to use Python's built-in web server, starting with a simple Hello, World! example and gradually introducing more complex functionalities, including handling different HTTP methods (GET, POST, PUT, DELETE, and PATCH) and sending requests using curl. The built-in web server is a useful tool for development and testing, allowing you to quickly set up a web server and serve static content. Understanding how to use and extend the built-in web server can significantly improve your development workflow and help you create more dynamic and responsive applications.