Create Simple Web Services with the Python http.server and socketserver Modules

Click to share! ⬇️

Welcome to our tutorial on creating simple web services with the Python http.server and socketserver modules! In today’s world, web services play a crucial role in enabling communication between different applications and systems. Whether you’re building a microservices architecture, integrating with third-party APIs, or simply looking to expose your application’s functionality to others, web services are an essential tool in any developer’s toolbox.

In this tutorial, we will guide you through the process of creating a simple, yet fully functional web service using Python’s built-in http.server and socketserver modules. These modules make it incredibly easy to get started with creating web services without the need for additional dependencies or complex configurations.

Throughout this tutorial, you’ll learn how to:

By the end of this tutorial, you’ll have a solid understanding of how to create, customize, and deploy web services using Python’s http.server and socketserver modules. So, let’s dive in and start building your first web service!

How To Install http.server and socketserver Modules

The http.server and socketserver modules are part of Python’s standard library, which means you don’t need to install them separately. As long as you have a compatible version of Python installed on your system, these modules will already be available for you to use.

To ensure you have the required version of Python, follow these steps:

  1. Check your Python version: Open a terminal or command prompt and type the following command to check your Python version:
python --version

or

python3 --version

For this tutorial, you should have Python 3.6 or later installed. If you have an older version or don’t have Python installed, proceed to the next step.

  1. Install Python: If you need to install or upgrade Python, visit the official Python website (https://www.python.org/downloads/) to download the latest version for your operating system. Follow the installation instructions provided on the website.

Once you have a compatible version of Python installed, you can start using the http.server and socketserver modules without any additional setup. Simply import them in your Python script like this:

import http.server
import socketserver

Now you’re ready to start building your web service with the http.server and socketserver modules!

How To Create a Basic HTTP Server

Creating a basic HTTP server using Python’s http.server and socketserver modules is incredibly simple. In this section, we’ll walk you through the steps to set up and run a basic HTTP server that serves static files from a directory.

  1. Create a directory for your server: First, choose a directory where you want to serve files from. This could be an existing directory containing static files (e.g., HTML, CSS, JavaScript, images) or a new empty directory. For the sake of this tutorial, create a new directory named my_server and navigate to it in your terminal or command prompt.
  2. Create a Python script: Inside the my_server directory, create a new Python script named basic_http_server.py. Open this file in your favorite code editor.
  3. Import necessary modules: Add the following lines at the beginning of basic_http_server.py to import the required modules:
import http.server
import socketserver
  1. Define server settings: Next, define the server’s address and port number. You can choose any available port number, but for this example, we’ll use port 8080. Add the following lines to your script:
HOST = "localhost"
PORT = 8080
  1. Create the server: Now, create an instance of the socketserver.TCPServer class with the defined host and port, and use the http.server.SimpleHTTPRequestHandler as the request handler. Add the following lines to your script:
Handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer((HOST, PORT), Handler)
  1. Run the server: Finally, add the following lines to start the server and keep it running indefinitely:
print(f"Serving on http://{HOST}:{PORT}")
httpd.serve_forever()
  1. Save and run your script: Save your basic_http_server.py file and run it from the terminal or command prompt:
python basic_http_server.py

or

python3 basic_http_server.py

You should see the following output:

Serving on http://localhost:8080

Your basic HTTP server is now up and running, serving files from the my_server directory. Open your web browser and navigate to http://localhost:8080. If you have any static files in the directory, you should be able to access them through the browser. If the directory is empty, you’ll see an empty file listing.

To stop the server, press Ctrl+C in the terminal or command prompt where it’s running.

How To Implement Custom Request Handlers

Custom request handlers allow you to define how your server responds to different types of HTTP requests. By implementing custom request handlers, you can create dynamic responses based on the request’s content, path, or any other attribute.

In this section, we’ll show you how to create a custom request handler by subclassing Python’s http.server.BaseHTTPRequestHandler.

  1. Create a new Python script: Create a new Python script named custom_http_server.py in your project directory and open it in your favorite code editor.
  2. Import necessary modules: Add the following lines at the beginning of custom_http_server.py to import the required modules:
import http.server
import socketserver
  1. Define server settings: Define the server’s address and port number, just like in the previous example:
HOST = "localhost"
PORT = 8080
  1. Create a custom request handler class: To create a custom request handler, subclass http.server.BaseHTTPRequestHandler and override the methods that handle different HTTP request methods, such as do_GET, do_POST, etc. In this example, we’ll override the do_GET method to send a custom response. Add the following class definition to your script:
class CustomRequestHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        # Send a response header
        self.send_response(200)
        self.send_header("Content-Type", "text/html")
        self.end_headers()

        # Prepare a custom response
        response = "<html><head><title>Custom HTTP Server</title></head>"
        response += "<body><h1>Hello from the custom HTTP server!</h1></body></html>"

        # Send the response
        self.wfile.write(response.encode())

In this example, we’re sending a simple HTML response with a “Hello from the custom HTTP server!” message.

  1. Create the server: Now, create an instance of the socketserver.TCPServer class with the defined host and port, and use the CustomRequestHandler as the request handler. Add the following lines to your script:
httpd = socketserver.TCPServer((HOST, PORT), CustomRequestHandler)
  1. Run the server: Finally, add the following lines to start the server and keep it running indefinitely:
print(f"Serving on http://{HOST}:{PORT}")
httpd.serve_forever()
  1. Save and run your script: Save your custom_http_server.py file and run it from the terminal or command prompt:
python custom_http_server.py

or

python3 custom_http_server.py

You should see the following output:

Serving on http://localhost:8080

Now, open your web browser and navigate to http://localhost:8080. You should see the “Hello from the custom HTTP server!” message in your browser, indicating that your custom request handler is working as expected.

To stop the server, press Ctrl+C in the terminal or command prompt where it’s running.

How To Build a Simple RESTful Web Service

A RESTful web service is an API that adheres to the principles of Representational State Transfer (REST). These services use standard HTTP methods (such as GET, POST, PUT, and DELETE) to perform operations on resources, which are identified by URIs.

In this section, we’ll show you how to build a simple RESTful web service using Python’s http.server and socketserver modules.

  1. Create a new Python script: Create a new Python script named restful_api.py in your project directory and open it in your favorite code editor.
  2. Import necessary modules: Add the following lines at the beginning of restful_api.py to import the required modules:
import json
import http.server
import socketserver
  1. Define server settings: Define the server’s address and port number, just like in the previous examples:
HOST = "localhost"
PORT = 8080
  1. Create a custom request handler class: To create a custom request handler for your RESTful web service, subclass http.server.BaseHTTPRequestHandler and override the methods that handle different HTTP request methods. In this example, we’ll implement a simple in-memory key-value store with GET and POST methods. Add the following class definition to your script:
class RESTfulRequestHandler(http.server.BaseHTTPRequestHandler):
    # In-memory key-value store
    store = {}

    def do_GET(self):
        # Extract the key from the request path
        key = self.path.lstrip('/')

        # Check if the key exists in the store
        if key in self.store:
            # Send a response header
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.end_headers()

            # Prepare and send the response
            response = json.dumps({"value": self.store[key]}).encode()
            self.wfile.write(response)
        else:
            # Send a 404 Not Found response
            self.send_response(404)
            self.end_headers()

    def do_POST(self):
        # Extract the key from the request path
        key = self.path.lstrip('/')

        # Read the request body
        content_length = int(self.headers.get("Content-Length"))
        raw_data = self.rfile.read(content_length)
        data = json.loads(raw_data)

        # Store the value in the key-value store
        self.store[key] = data["value"]

        # Send a 204 No Content response
        self.send_response(204)
        self.end_headers()
  1. Create the server: Now, create an instance of the socketserver.TCPServer class with the defined host and port, and use the RESTfulRequestHandler as the request handler. Add the following lines to your script:
httpd = socketserver.TCPServer((HOST, PORT), RESTfulRequestHandler)
  1. Run the server: Add the following lines to start the server and keep it running indefinitely:
print(f"Serving on http://{HOST}:{PORT}")
httpd.serve_forever()
  1. Save and run your script: Save your restful_api.py file and run it from the terminal or command prompt:
python restful_api.py

or

python3 restful_api.py

You should see the following output:

Serving on http://localhost:8080

Your simple RESTful web service is now up and running. To test it, you can use tools like curl or applications like Postman.

How To Add JSON Support to Your Web Service

Adding JSON support to your web service allows you to send and receive data in a structured, widely accepted format. In this section, we’ll show you how to modify your RESTful web service to accept and return JSON payloads.

We’ll be building upon the RESTful web service created in the previous section. If you haven’t done so already, follow the steps there to create a simple RESTful web service using Python’s http.server and socketserver modules.

  1. Import the JSON module: Ensure the following line is at the beginning of your Python script to import the json module:
import json
  1. Modify the do_GET method: Update the do_GET method in your RESTfulRequestHandler class to return JSON data. The response should include the appropriate Content-Type header and be encoded before sending it. Here’s the updated do_GET method:
def do_GET(self):
    # Extract the key from the request path
    key = self.path.lstrip('/')

    # Check if the key exists in the store
    if key in self.store:
        # Send a response header
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.end_headers()

        # Prepare and send the response
        response = json.dumps({"value": self.store[key]}).encode()
        self.wfile.write(response)
    else:
        # Send a 404 Not Found response
        self.send_response(404)
        self.end_headers()
  1. Modify the do_POST method: Update the do_POST method in your RESTfulRequestHandler class to accept JSON data in the request body. Read the Content-Length header to determine the size of the incoming payload, then parse the JSON data using the json.loads() function. Here’s the updated do_POST method:
def do_POST(self):
    # Extract the key from the request path
    key = self.path.lstrip('/')

    # Read the request body
    content_length = int(self.headers.get("Content-Length"))
    raw_data = self.rfile.read(content_length)
    data = json.loads(raw_data)

    # Store the value in the key-value store
    self.store[key] = data["value"]

    # Send a 204 No Content response
    self.send_response(204)
    self.end_headers()

With these modifications, your web service now supports sending and receiving JSON data. To test your updated web service, use tools like curl or applications like Postman to send GET and POST requests with JSON payloads.

How To Secure Your Web Service with HTTPS

Securing your web service with HTTPS helps protect the data transmitted between the server and clients by encrypting the communication. In this section, we’ll show you how to use SSL/TLS to secure your web service.

  1. Obtain an SSL/TLS certificate: To use HTTPS, you’ll need an SSL/TLS certificate. For production use, you should obtain a certificate from a trusted Certificate Authority (CA) like Let’s Encrypt or purchase one from a commercial CA. For testing and development purposes, you can create a self-signed certificate using OpenSSL. Run the following command to create a self-signed certificate and a private key:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

Fill in the required information, and you will get two files: key.pem (private key) and cert.pem (certificate).

  1. Import necessary modules: Add the following line at the beginning of your Python script to import the ssl module:
import ssl
  1. Modify the server creation code: Update the code in your script where the server is created. Instead of using socketserver.TCPServer, use http.server.HTTPServer and wrap it with the ssl.wrap_socket() function. Provide the paths to your certificate and private key files.

Replace the following line:

httpd = socketserver.TCPServer((HOST, PORT), RESTfulRequestHandler)

with:

httpd = http.server.HTTPServer((HOST, PORT), RESTfulRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile="cert.pem", keyfile="key.pem", server_side=True)
  1. Update the serving message: Change the serving message from http to https:
print(f"Serving on https://{HOST}:{PORT}")
  1. Save and run your script: Save your updated script and run it from the terminal or command prompt:
python restful_api.py

or

python3 restful_api.py

You should see the following output:

Serving on https://localhost:8080

Your web service is now secured with HTTPS.

How To Handle Different HTTP Methods

Handling different HTTP methods allows your web service to respond appropriately to various types of requests (GET, POST, PUT, DELETE, etc.). In this section, we’ll show you how to handle different HTTP methods in your Python web service using the http.server and socketserver modules.

  1. Create a custom request handler class: If you haven’t already, create a custom request handler by subclassing http.server.BaseHTTPRequestHandler. We’ll add methods to handle different HTTP requests.
class CustomRequestHandler(http.server.BaseHTTPRequestHandler):
    pass
  1. Handle GET requests: To handle GET requests, override the do_GET() method in your custom request handler class. This method is called when the server receives a GET request.
def do_GET(self):
    # Your code to handle GET requests goes here
    pass
  1. Handle POST requests: To handle POST requests, override the do_POST() method in your custom request handler class. This method is called when the server receives a POST request.
def do_POST(self):
    # Your code to handle POST requests goes here
    pass
  1. Handle PUT requests: To handle PUT requests, override the do_PUT() method in your custom request handler class. This method is called when the server receives a PUT request.
def do_PUT(self):
    # Your code to handle PUT requests goes here
    pass
  1. Handle DELETE requests: To handle DELETE requests, override the do_DELETE() method in your custom request handler class. This method is called when the server receives a DELETE request.
def do_DELETE(self):
    # Your code to handle DELETE requests goes here
    pass
  1. Create the server: Now, create an instance of the socketserver.TCPServer class with the defined host and port, and use the CustomRequestHandler as the request handler.
httpd = socketserver.TCPServer((HOST, PORT), CustomRequestHandler)
  1. Run the server: Add the following lines to start the server and keep it running indefinitely:
print(f"Serving on http://{HOST}:{PORT}")
httpd.serve_forever()

Now your web service can handle different HTTP methods by implementing the corresponding do_* methods in your custom request handler class. Add the appropriate logic for each method to process the incoming requests and send appropriate responses.

How To Deploy Your Web Service on a Server

Deploying your web service on a server makes it accessible to users on the internet. In this section, we’ll show you how to deploy your Python web service using a popular web server, such as Apache with mod_wsgi or using a platform as a service (PaaS) like Heroku.

Option 1: Deploying with Apache and mod_wsgi

  1. Install Apache: Install the Apache web server on your server machine. For Ubuntu or Debian-based systems, use the following command:
sudo apt-get install apache2

For CentOS or RHEL-based systems, use:

sudo yum install httpd
  1. Install mod_wsgi: Install the mod_wsgi module, which allows Apache to serve Python web applications. For Ubuntu or Debian-based systems, use:
sudo apt-get install libapache2-mod-wsgi-py3

For CentOS or RHEL-based systems, use:

sudo yum install mod_wsgi
  1. Create a WSGI file: Create a file named your_app_name.wsgi in your project directory and add the following code:
import sys
sys.path.insert(0, "/path/to/your/project")

from your_main_script import app as application

Replace /path/to/your/project with the actual path to your project directory and your_main_script with the name of the script containing your web service.

  1. Configure Apache: Create a new Apache configuration file for your web service in the appropriate directory (usually /etc/apache2/sites-available/ or /etc/httpd/conf.d/). Name the file your_app_name.conf and add the following content:
<VirtualHost *:80>
    ServerName yourdomain.com
    ServerAlias www.yourdomain.com

    WSGIDaemonProcess your_app_name user=www-data group=www-data threads=5
    WSGIScriptAlias / /path/to/your/project/your_app_name.wsgi

    <Directory /path/to/your/project>
        WSGIProcessGroup your_app_name
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>

Replace yourdomain.com, www.yourdomain.com, your_app_name, and /path/to/your/project with the appropriate values for your project.

  1. Enable the site: Enable the new site configuration using the a2ensite command (Ubuntu or Debian-based systems):
sudo a2ensite your_app_name.conf

For CentOS or RHEL-based systems, make sure the configuration file is in the /etc/httpd/conf.d/ directory.

  1. Restart Apache: Restart the Apache web server to apply the changes:
sudo service apache2 restart

or

sudo systemctl restart httpd

Now, your web service should be accessible at your domain.

Option 2: Deploying on Heroku

  1. Sign up for Heroku: If you haven’t already, sign up for a free account at Heroku.
  2. Install Heroku CLI: Install the Heroku CLI on your local machine.
  3. Create a requirements.txt file: List your project’s dependencies in a requirements.txt file in your project directory.
  4. Create a Procfile: Create a file named Procfile (without any file extension) in your project directory and add the following content:
web: gunicorn your_main_script:app

Replace your_main_script with the name of the script containing your web service. Make sure you have Gunicorn installed; if not, add it to your requirements.txt file.

  1. Initialize a Git repository: If your project is not already a Git repository, initialize one with the following command:
git init
  1. Commit your changes: Commit your project files to the repository:
git add .
git commit -m "Initial commit"
  1. Log in to Heroku: Use the Heroku CLI to log in to your account:
heroku login
  1. Create a new Heroku app: Create a new app on Heroku:
heroku create your_app_name

Replace your_app_name with a unique name for your app.

  1. Deploy your app: Push your code to the Heroku remote repository:
git push heroku main
  1. Open your app: Use the following command to open your app in a web browser:
heroku open

Your web service should now be accessible at https://your_app_name.herokuapp.com.

These are two popular ways to deploy your Python web service. Depending on your requirements and infrastructure, you might choose other deployment options, such as using Nginx with uWSGI, or deploying on cloud platforms like AWS, Google Cloud, or Microsoft Azure.

Click to share! ⬇️