Flaskless
Although Flask is popular, it certainly isn’t necessary! Indeed, you can implement web applications using Python’s own built-in http
library.
Consider the program, below, which implements a simple web application that (only) returns a static HTML page.
# Implements a web server
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
class HTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Handle GET requests
def do_GET(self):
# Respond with status code
self.send_response(200)
# Respond with headers
self.send_header("Content-type", "text/html")
self.end_headers()
# Respond with body
self.wfile.write(b"""
<!DOCTYPE html>
<html lang="en">
<head>
<title>hello</title>
</head>
<body>
hello, world
</body>
</html>
""")
# Run server
port = 8080
httpd = HTTPServer(("0.0.0.0", port), HTTPServer_RequestHandler)
print(f"Running on https://{os.environ.get('C9_HOSTNAME')}:{port}")
print("Press CTRL+C to quit")
httpd.serve_forever()
If you copy and paste that code into a file called, e.g., hello.py
, run python hello.py
, and then visit the outputted URL, you should see a greeting!
Flask, of course, does much more than just return static HTML pages. Flask also “parses” HTTP requests, extracting from each request’s “path” the desired route as well as the names and values of any HTTP parameters. For instance, a path like
/search?q=cats
has a route of /search
and an HTTP parameter named q
, the value of which is cats
. A question mark (?
) separates the two.
If a path contains multiple parameters, those key-value pairs are separated by ampersands (&
). For instance, if you visit amazon.com and search for “duck”, odds are you’ll find yourself at a URL like
https://www.amazon.com/s?k=duck&ref=nb_sb_noss_2
which has a route of /s
and two parameters: k
, whose value is duck
, and ref
, whose value is nb_sb_noss_2
(or similar).
Let’s implement parsing.
-
(6 points.) In
flaskless/server.py
, complete the implementation ofparse
in such a way that the function parsespath
, returning alist
whose first element is astr
representing the path’s route and whose second element is adict
representing the path’s parameters. For instance, ifpath
is/greet?first=Cody&last=Murphey
then
parse
should return:['/greet', {'first': 'Cody', 'last': 'Murphey'}]
Assume that
path
will contain no more than one question mark. And assume that any parameters will have both a name and a value, neither of which will contain&
or=
(except for one=
between them). If there is no question mark inpath
or if there are no parameters inpath
, then yourdict
should be empty. For instance, ifpath
is just/
or even/?
, thenparse
should return:['/', {}]
You might find
split
of some help!
Flask also supports HTML templates, which allows us to replace placeholders in those templates with the values of variables. Recall that those placeholders are surrounded by {{
and }}
.
Let’s implement templating.
-
(6 points.) In
flaskless/server.py
, complete the implementation ofrender_template
in such a way that it openstemplate
, reads its contents, and replaces any placeholders therein with values fromargs
. For instance, suppose thattemplate
istemplates/greet.html
andargs
is:{'first': 'Cody', 'last': 'Murphey'}
. Thenrender_template
should opentemplates/greet.html
, read its contents, and replace any instances of{{ first }}
therein withCody
and any instances of{{ last }}
therein withMurphey
, thereafter returning the resultingstr
. Assume that each{{
will be followed by a single space, followed by the name of a variable, followed by a single space, followed by}}
. And assume thatargs
will have keys (and values) for all variables in a template. No need to support{%
and%}
.You might find
open
,read
,replace
, andclose
(orwith
) of some help!
Once you have implemented both parse
and render_template
, you should be able to cd
into flaskless
and run:
python server.py
If you then visit the outputted URL, you should see a form (the contents of templates/index.html
). If you submit that form, you should see a greeting!
If you make any changes to server.py
thereafter, be sure to stop the server with CTRL+C and re-run it.