Skip to content
Advertisement

Create web server using ONLY standard library

I would like to implement a web page in Python using ONLY the std library.

I have done it in PHP but I want to do it in Python and it is very difficult to me to understand the documentation.

This is what I done in PHP:

Access http://localhost:8888/project/src/car.php.

The user has to complete a form where it specifies the brand of the car.
Then the site returns the JSON list of cars in http://localhost:8888/project/src/car.php?brand=toyota
It works very well.

It was very easy in PHP, but I could not find a way to do that in Python using only standard library.
Do you have any suggestion ?

This is what I have so far:

server.py:

import http.server
import socketserver

if __name__ == '__main__':
    PORT = 8888
    Handler = http.server.SimpleHTTPRequestHandler
    with socketserver.TCPServer(("", PORT), Handler) as httpd:
        print("serving at port", PORT)
        httpd.serve_forever()

index.html:

<!-- used to make a form for the user -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Autocompletion</title>
</head>
<body>
<h2>Manufacturer finder</h2>

<p>
    Please enter your research
</p>

<form action="car.py" method="get" class="form-example">
    <div class="form-example">
        <label for="brand">Enter your query: </label>
        <input type="text" name="brand" id="brand" required>
    </div>
    <div class="form-example">
        <input type="submit" value="Submit">
    </div>
</form>

</body>
</html>

The user land on index.html that has a form to be completed. When a user complete the form, this open the file : http://localhost:8888/car.py?brand=toyota

The script works in http://localhost:8888/ and not http://localhost:8888/car.py (as does my PHP script) but it is not a problem.

After the form is filled, I don’t know how to retrieve the variable manufacturer and display the list of cars from the brand. Inside car.py I have a list of cars for each brand I just need so I just need to fetch the correct cars from the brand and print it as a JSON only without additional HTML.

The problem I have: Completing the form just print the entire car.py file.

It is not a problem to have a form not secure (where you can have the results by appending ?brand=toyota to the url).

This is how I start the server:

python server.py

Do you have any suggestions ?
Thank you for you attention

Advertisement

Answer

The documentation for the handler class you’ve chosen quite clearly says

This class serves files from the current directory and below, directly mapping the directory structure to HTTP requests.

which is why you’re seeing the content of car.py.

You’ll have to implement your own handler class, deriving from BaseHTTPRequestHandler, to serve your needs. This simple example only parses and returns the query string as JSON when you access /data.

As an aside, comparing PHP and Python here (“it was easy in PHP”) is rather apples-and-oranges; with PHP, you also have something (be it Apache, Nginx, PHP-FPM, PHP’s built-in web server) to process requests and choose which script to use, invoke it, etc., wherein here you’re doing everything from scratch.

import urllib.parse
import http.server
import socketserver
import json


class CarHandler(http.server.SimpleHTTPRequestHandler):
    def _send_content(self, data, status=200, content_type="text/plain"):
        if isinstance(data, str):
            data = data.encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", content_type)
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)
        self.wfile.flush()

    def do_GET(self):
        url = urllib.parse.urlparse(self.path)
        if url.path == "/":
            return self._send_content(
                "<form method=get action=/data><input type=search name=q><input type=submit></form>",
                content_type="text/html",
            )
        elif url.path == "/data":
            qs = urllib.parse.parse_qs(url.query)
            return self._send_content(json.dumps(qs), content_type="application/json")
        else:
            return self._send_content(f"404: {url}", status=400)


if __name__ == "__main__":
    PORT = 8891
    with socketserver.TCPServer(("", PORT), CarHandler) as httpd:
        print("serving at port", PORT)
        httpd.serve_forever()
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement