Parsing the Request - GetΒΆ

Run the environment.py script again and this time call it like this:

http://localhost:8051/?age=10&hobbies=software&hobbies=tunning

Check the QUERY_STRING and the REQUEST_METHOD variables in the environ dictionary:

QUERY_STRING: age=10&hobbies=software&hobbies=tunning
REQUEST_METHOD: GET

When the request method is GET the form variables will be sent in the URL in the part called query string, that is, everything after the ?

Notice the hobbies variable appears two times. It can happen when there are checkboxes in the form or when the user type the same variable more than once in the URL.

It is possible to write code to parse the query string and retrieve those values but it is easier to use the cgi.parse_qs() function which returns a dictionary with the values as lists.

Always beware of the user input. Sanitise it to avoid script injection. The cgi.escape() function can be used for that.

The HTML’s form tag in this script instructs the browser to do a GET request (method="get"):

#!/usr/bin/env python

from wsgiref.simple_server import make_server
from cgi import parse_qs, escape

html = """
<html>
<body>
   <form method="get" action="">
        <p>
           Age: <input type="text" name="age" value="%(age)s">
        </p>
        <p>
            Hobbies:
            <input
                name="hobbies" type="checkbox" value="software"
                %(checked-software)s
            > Software
            <input
                name="hobbies" type="checkbox" value="tunning"
                %(checked-tunning)s
            > Auto Tunning
        </p>
        <p>
            <input type="submit" value="Submit">
        </p>
    </form>
    <p>
        Age: %(age)s<br>
        Hobbies: %(hobbies)s
    </p>
</body>
</html>
"""

def application (environ, start_response):

    # Returns a dictionary in which the values are lists
    d = parse_qs(environ['QUERY_STRING'])

    # As there can be more than one value for a variable then
    # a list is provided as a default value.
    age = d.get('age', [''])[0] # Returns the first age value
    hobbies = d.get('hobbies', []) # Returns a list of hobbies

    # Always escape user input to avoid script injection
    age = escape(age)
    hobbies = [escape(hobby) for hobby in hobbies]

    response_body = html % { # Fill the above html template in
        'checked-software': ('', 'checked')['software' in hobbies],
        'checked-tunning': ('', 'checked')['tunning' in hobbies],
        'age': age or 'Empty',
        'hobbies': ', '.join(hobbies or ['No Hobbies?'])
    }

    status = '200 OK'

    # Now content type is text/html
    response_headers = [
        ('Content-Type', 'text/html'),
        ('Content-Length', str(len(response_body)))
    ]

    start_response(status, response_headers)
    return [response_body]

httpd = make_server('localhost', 8051, application)

# Now it is serve_forever() in instead of handle_request()
httpd.serve_forever()

Listening at http://localhost:8051

As the server above will run forever (serve_forever) it is necessary to interrupt it possibly with a Ctrl-C