The best way to learn how a program works is to write that program yourself. You want to learn how servers work? Great! Try and write one on your own. Even if you fail, I guarantee you will learn something out of the whole experience. In this post, I will show you how to create your very own server that accepts POST requests. But, I won’t show you how to create the whole thing from scratch. I will be focusing on how to handle a POST request and return a response from the output of a Python script. This will allow us to use create a web form that takes in a user’s name from a text box, and display it on a web page. This is a fairly trivial task with a web framework like Flask or Pyramid, but we’re going be handling things a much lower level, so it will be a bit trickier.
Python already has a couple of modules that contains a classes that can serve files from the current directory. It can serve plain text, and HTML. This module will start us out with a very rudimentary server that handles GET requests.
To start with, create a file called myserver.py and place the following code in there:
To create an instance of HTTPServer, you must pass two arguments: the server address in the form of a tuple, and a request handler. SimpleHTTPRequestHandler is a class that handles the requests coming in from the client (more about that later).
Now run the script and open up a web browser and go to http://localhost:8000/. That will list the contents of the directory the script was run in. If there were any HTML files in there, the browser should display a hyperlink to that HTML page and properly render the it, after clicking on it. This basic server can only handle two types of requests: GET and HEAD. It does not handle POST requests. Let’s try and send a POST request anyway to see what happens. Run the script. If you don’t have the commandline tool netcat, go download it. With netcat, connect to localhost on port 8000:
Following the HTTP protocol, to send a POST request we need three things:
- the method type
- the path
- and the HTTP version.
After connecting with netcat, type this:
Hit Enter twice and you will get the following response:
If you take a look at the source code for SimpleHTTPServer, you can view the SimpleHTTPRequestHandler.Notice that it has methods called do_GET() and do_HEAD():
We can easily extend the functionality of the BaseHTTPRequestHandler by creating our own handler class that inherits from it. Then, we can extend that class by creating a method called do_POST() that will handle the POST requests.
Of course, this code actually won’t do anything. But, if you try and send another POST request to the server (like we did with netcat above), you won’t get the error anymore. Try sending another POST with netcat. You’ll see that you don’t get any response.
When a browser sends POST requests, it will send the request line like we sent, followed by the headers. Before we write any code to handle the request, let’s see exactly what a browser will send us when sending a POST request via a web form. Put the following HTML in a file called index.html:
So, we have a form that takes in text input, and submits a script called hello.py (which we didn’t create yet). Open up another terminal and use netcat to listen on port 8000:
Now open up that index.html file with a web browser. Go ahead and enter your name and click submit. After you submit, you’ll notice something like this in the terminal:
Notice at the very end, there is a key-value pair separated by an equals sign. The first part (first_name) is what we called the name attribute in that text input above:
The second part, after the equals sign, is the name you entered in the text box. What we want to do, is write a script that takes that name and spits back some HTML with the name you entered. Now let’s create the hello.py. This is going to contain the program that takes the name a user entered, and displays it back to the user like this:
That script looks like this:
The first line contains what’s called a shebang followed a file path, and python. Basically, this will help allow the operating system to run the program as an executable file. To make sure that our OS can indeed run this program as an executable, type this in the terminal:
Now, the file is executable. This will allow our server to run the script.
Back to myserver.py. Here is the full script:
To see this in action:
- python myserver.py
- Navigate to http://localhost:8000/
- Enter your name and hit submit.
Pretty simple.